X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=3051f5ac9d93771620536c019413d08420dceec0;hb=9de8eede744c45187c7011543ef8097d1ebc879c;hp=61baa07ce653f8907193700e2a6b1d1071afb30c;hpb=95566a9d19e926d3fc4868efda00b2cabe6955d6;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 61baa07c..3051f5ac 100644 --- a/src/game.c +++ b/src/game.c @@ -89,6 +89,9 @@ #define DOUBLE_PLAYER_SPEED(p) (HALVE_MOVE_DELAY((p)->move_delay_value)) #define HALVE_PLAYER_SPEED(p) (DOUBLE_MOVE_DELAY((p)->move_delay_value)) +/* values for other actions */ +#define MOVE_STEPSIZE_NORMAL (TILEX / MOVE_DELAY_NORMAL_SPEED) + #define INIT_GFX_RANDOM() (SimpleRND(1000000)) #define GET_NEW_PUSH_DELAY(e) ( (element_info[e].push_delay_fixed) + \ @@ -163,9 +166,12 @@ static void CloseAllOpenTimegates(void); static void CheckGravityMovement(struct PlayerInfo *); static void KillHeroUnlessProtected(int, int); -static void CheckTriggeredElementChange(int, int); -static void CheckPlayerElementChange(int, int, int, int); -static void ChangeElementDoIt(int, int, int); +static void TestIfPlayerTouchesCustomElement(int, int); +static void TestIfElementTouchesCustomElement(int, int); + +static boolean CheckTriggeredElementChange(int, int, int, int); +static boolean CheckElementChange(int, int, int, int); +static void ChangeElementNow(int, int, int); static void PlaySoundLevel(int, int, int); static void PlaySoundLevelNearest(int, int, int); @@ -202,8 +208,8 @@ static void RunTimegateWheel(int x, int y); struct ChangingElementInfo { - int base_element; - int next_element; + int element; + int target_element; int change_delay; void (*pre_change_function)(int x, int y); void (*change_function)(int x, int y); @@ -352,14 +358,70 @@ static struct ChangingElementInfo changing_element_list[] = } }; -static struct ChangingElementInfo changing_element[MAX_NUM_ELEMENTS]; +struct +{ + int element; + int push_delay_fixed, push_delay_random; +} +push_delay_list[] = +{ + { EL_SPRING, 0, 0 }, + { EL_BALLOON, 0, 0 }, + + { EL_SOKOBAN_OBJECT, 2, 0 }, + { EL_SOKOBAN_FIELD_FULL, 2, 0 }, + { EL_SATELLITE, 2, 0 }, + { EL_SP_DISK_YELLOW, 2, 0 }, + + { EL_UNDEFINED, 0, 0 }, +}; + +struct +{ + int element; + int move_stepsize; +} +move_stepsize_list[] = +{ + { EL_AMOEBA_DROP, 2 }, + { EL_AMOEBA_DROPPING, 2 }, + { EL_QUICKSAND_FILLING, 1 }, + { EL_QUICKSAND_EMPTYING, 1 }, + { EL_MAGIC_WALL_FILLING, 2 }, + { EL_BD_MAGIC_WALL_FILLING, 2 }, + { EL_MAGIC_WALL_EMPTYING, 2 }, + { EL_BD_MAGIC_WALL_EMPTYING, 2 }, + + { EL_UNDEFINED, 0 }, +}; + +struct +{ + int element; + int gem_count; +} +gem_count_list[] = +{ + { EL_EMERALD, 1 }, + { EL_BD_DIAMOND, 1 }, + { EL_EMERALD_YELLOW, 1 }, + { EL_EMERALD_RED, 1 }, + { EL_EMERALD_PURPLE, 1 }, + { EL_DIAMOND, 3 }, + { EL_SP_INFOTRON, 1 }, + { EL_PEARL, 5 }, + { EL_CRYSTAL, 8 }, + + { EL_UNDEFINED, 0 }, +}; + +static boolean changing_element[MAX_NUM_ELEMENTS]; static unsigned long trigger_events[MAX_NUM_ELEMENTS]; -#define IS_AUTO_CHANGING(e) (changing_element[e].base_element != EL_UNDEFINED) +#define IS_AUTO_CHANGING(e) (changing_element[e]) #define IS_JUST_CHANGING(x, y) (ChangeDelay[x][y] != 0) #define IS_CHANGING(x, y) (IS_AUTO_CHANGING(Feld[x][y]) || \ IS_JUST_CHANGING(x, y)) -#define TRIGGERS_BY_COLLECTING(e) (trigger_events[e] & CE_OTHER_COLLECTING) void GetPlayerConfig() @@ -688,6 +750,8 @@ static void InitGameEngine() printf(" => game.engine_version == %06d\n", game.engine_version); #endif + /* ---------- initialize player's initial move delay --------------------- */ + /* 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 : @@ -697,50 +761,84 @@ static void InitGameEngine() game.initial_move_delay_value = (level.double_speed ? MOVE_DELAY_HIGH_SPEED : MOVE_DELAY_NORMAL_SPEED); + /* ---------- initialize changing elements ------------------------------- */ + /* initialize changing elements information */ for (i=0; ibase_element; + struct ElementChangeInfo *change = &element_info[element].change; + +#if 1 + change->target_element = ce->target_element; + change->delay_fixed = ce->change_delay; + change->pre_change_function = ce->pre_change_function; + change->change_function = ce->change_function; + change->post_change_function = ce->post_change_function; + changing_element[element] = TRUE; +#else changing_element[element].base_element = ce->base_element; changing_element[element].next_element = ce->next_element; changing_element[element].change_delay = ce->change_delay; changing_element[element].pre_change_function = ce->pre_change_function; changing_element[element].change_function = ce->change_function; changing_element[element].post_change_function = ce->post_change_function; - - i++; +#endif } /* add changing elements from custom element configuration */ for (i=0; i < NUM_CUSTOM_ELEMENTS; i++) { int element = EL_CUSTOM_START + i; +#if 0 struct ElementChangeInfo *change = &element_info[element].change; +#endif /* only add custom elements that change after fixed/random frame delay */ if (!CAN_CHANGE(element) || !HAS_CHANGE_EVENT(element, CE_DELAY)) continue; +#if 1 + changing_element[element] = TRUE; +#else changing_element[element].base_element = element; - changing_element[element].next_element = change->successor; + changing_element[element].next_element = change->target_element; changing_element[element].change_delay = (change->delay_fixed * change->delay_frames); +#endif } + /* ---------- initialize trigger events ---------------------------------- */ + /* initialize trigger events information */ for (i=0; iPushing && player->MovPos != 0); -#else - boolean pushing = (player != NULL && player->Pushing && player->is_moving); -#endif - -#if 0 - if (player && player->is_moving && player->MovPos == 0) - printf("::: !!!\n"); -#endif - - if (element == EL_AMOEBA_DROP || element == EL_AMOEBA_DROPPING) - step /= 2; - else if (element == EL_QUICKSAND_FILLING || - element == EL_QUICKSAND_EMPTYING) - step /= 4; - else if (element == EL_MAGIC_WALL_FILLING || - element == EL_BD_MAGIC_WALL_FILLING || - element == EL_MAGIC_WALL_EMPTYING || - element == EL_BD_MAGIC_WALL_EMPTYING) - step /= 2; - else if (CAN_FALL(element) && horiz_move && - y < lev_fieldy-1 && IS_BELT_ACTIVE(Feld[x][y+1])) - step /= 2; - else if (element == EL_SPRING && horiz_move) - step *= 2; - else if (IS_CUSTOM_ELEMENT(element)) - step = SIGN(step) * element_info[element].move_stepsize; + int nextx = newx + dx, nexty = newy + dy; + int horiz_move = (dx != 0); + int sign = (horiz_move ? dx : dy); + int step = sign * element_info[element].move_stepsize; + boolean pushed = Pushed[x][y]; -#if OLD_GAME_BEHAVIOUR - else if (CAN_FALL(element) && horiz_move && !IS_SP_ELEMENT(element)) - step*=2; -#endif + /* special values for move stepsize for spring and things on conveyor belt */ + if (horiz_move) + { + if (CAN_FALL(element) && + y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1])) + step = sign * MOVE_STEPSIZE_NORMAL / 2; + else if (element == EL_SPRING) + step = sign * MOVE_STEPSIZE_NORMAL * 2; + } MovPos[x][y] += step; -#if 1 -#if 1 - if (Pushed[x][y]) /* special case: moving object pushed by player */ -#else - if (pushing) /* special case: moving object pushed by player */ -#endif -#if 1 + if (pushed) /* special case: moving object pushed by player */ MovPos[x][y] = SIGN(MovPos[x][y]) * (TILEX - ABS(PLAYERINFO(x,y)->MovPos)); -#else - MovPos[x][y] = SIGN(MovPos[x][y]) * (TILEX - ABS(PLAYERINFO(x,y)->GfxPos)); -#endif -#endif - -#if 0 - if (element == EL_SPRING) - printf("::: spring moves %d [%d: %d, %d, %d/%d]\n", - MovPos[x][y], - pushing, - (player?player->Pushing:-42), - (player?player->is_moving:-42), - (player?player->MovPos:-42), - (player?player->GfxPos:-42)); -#endif if (ABS(MovPos[x][y]) >= TILEX) /* object reached its destination */ { @@ -3904,31 +4033,11 @@ void ContinueMoving(int x, int y) if (element == EL_MOLE) { - int i; - static int xy[4][2] = - { - { 0, -1 }, - { -1, 0 }, - { +1, 0 }, - { 0, +1 } - }; - Feld[x][y] = EL_SAND; - DrawLevelField(x, y); - - for(i=0; i<4; i++) - { - int xx, yy; - xx = x + xy[i][0]; - yy = y + xy[i][1]; - - if (IN_LEV_FIELD(xx, yy) && Feld[xx][yy] == EL_SAND) - DrawLevelField(xx, yy); /* for "crumbled sand" */ - } + DrawLevelFieldCrumbledSandNeighbours(x, y); } - - if (element == EL_QUICKSAND_FILLING) + else if (element == EL_QUICKSAND_FILLING) { element = Feld[newx][newy] = get_next_element(element); Store[newx][newy] = Store[x][y]; @@ -4002,34 +4111,35 @@ void ContinueMoving(int x, int y) ResetGfxAnimation(x, y); /* reset animation values for old field */ -#if 1 #if 0 + /* 2.1.1 (does not work correctly for spring) */ if (!CAN_MOVE(element)) MovDir[newx][newy] = 0; #else #if 0 + /* (does not work for falling objects that slide horizontally) */ if (CAN_FALL(element) && MovDir[newx][newy] == MV_DOWN) MovDir[newx][newy] = 0; #else + /* if (!CAN_MOVE(element) || (element == EL_SPRING && MovDir[newx][newy] == MV_DOWN)) MovDir[newx][newy] = 0; -#endif + */ + if (!CAN_MOVE(element) || + (CAN_FALL(element) && MovDir[newx][newy] == MV_DOWN)) + MovDir[newx][newy] = 0; #endif #endif DrawLevelField(x, y); DrawLevelField(newx, newy); -#if 0 - if (game.engine_version >= RELEASE_IDENT(2,2,0,7) || !pushing) -#endif - Stop[newx][newy] = TRUE; /* ignore this element until the next frame */ -#if 1 - if (!pushing) -#endif + Stop[newx][newy] = TRUE; /* ignore this element until the next frame */ + + if (!pushed) /* special case: moving object pushed by player */ JustStopped[newx][newy] = 3; if (DONT_TOUCH(element)) /* object may be nasty to player or others */ @@ -4041,15 +4151,15 @@ void ContinueMoving(int x, int y) else if (element == EL_PENGUIN) TestIfFriendTouchesBadThing(newx, newy); -#if 1 if (CAN_FALL(element) && direction == MV_DOWN && (newy == lev_fieldy - 1 || !IS_FREE(x, newy + 1))) Impact(x, newy); -#else - if (CAN_SMASH(element) && direction == MV_DOWN && - (newy == lev_fieldy - 1 || !IS_FREE(x, newy + 1))) - Impact(x, newy); -#endif + + if (!IN_LEV_FIELD(nextx, nexty) || !IS_FREE(nextx, nexty)) + CheckElementChange(newx, newy, element, CE_COLLISION); + + TestIfPlayerTouchesCustomElement(newx, newy); + TestIfElementTouchesCustomElement(newx, newy); } else /* still moving on */ { @@ -4941,12 +5051,16 @@ static void ChangeActiveTrap(int x, int y) DrawLevelFieldCrumbledSand(x, y); } -static void ChangeElementDoIt(int x, int y, int element_new) +static void ChangeElementNowExt(int x, int y, int target_element) { - CheckTriggeredElementChange(Feld[x][y], CE_OTHER_CHANGING); + if (IS_PLAYER(x, y) && !IS_ACCESSIBLE(target_element)) + { + Bang(x, y); + return; + } RemoveField(x, y); - Feld[x][y] = element_new; + Feld[x][y] = target_element; ResetGfxAnimation(x, y); ResetRandomAnimationValue(x, y); @@ -4958,41 +5072,111 @@ static void ChangeElementDoIt(int x, int y, int element_new) DrawLevelField(x, y); if (CAN_BE_CRUMBLED(Feld[x][y])) + DrawLevelFieldCrumbledSandNeighbours(x, y); +} + +static void ChangeElementNow(int x, int y, int element) +{ + struct ElementChangeInfo *change = &element_info[element].change; + + CheckTriggeredElementChange(x, y, Feld[x][y], CE_OTHER_IS_CHANGING); + + if (change->explode) { - int sx = SCREENX(x), sy = SCREENY(y); - static int xy[4][2] = - { - { 0, -1 }, - { -1, 0 }, - { +1, 0 }, - { 0, +1 } - }; - int i; + Bang(x, y); + return; + } - for(i=0; i<4; i++) + if (change->use_content) + { + boolean complete_change = TRUE; + boolean can_change[3][3]; + int xx, yy; + + for (yy = 0; yy < 3; yy++) for(xx = 0; xx < 3 ; xx++) { - int xx = x + xy[i][0]; - int yy = y + xy[i][1]; - int sxx = sx + xy[i][0]; - int syy = sy + xy[i][1]; + boolean half_destructible; + int ex = x + xx - 1; + int ey = y + yy - 1; + int e; + + can_change[xx][yy] = TRUE; + + if (ex == x && ey == y) /* do not check changing element itself */ + continue; + + if (change->content[xx][yy] == EL_EMPTY_SPACE) + { + can_change[xx][yy] = FALSE; /* do not change empty borders */ + + continue; + } + + if (!IN_LEV_FIELD(ex, ey)) + { + can_change[xx][yy] = FALSE; + complete_change = FALSE; - if (!IN_LEV_FIELD(xx, yy) || - !IN_SCR_FIELD(sxx, syy) || - !CAN_BE_CRUMBLED(Feld[xx][yy]) || - IS_MOVING(xx, yy)) continue; + } + + e = Feld[ex][ey]; + + half_destructible = (IS_FREE(ex, ey) || IS_DIGGABLE(e)); + + if ((change->power <= CP_NON_DESTRUCTIVE && !IS_FREE(ex, ey)) || + (change->power <= CP_HALF_DESTRUCTIVE && !half_destructible) || + (change->power <= CP_FULL_DESTRUCTIVE && IS_INDESTRUCTIBLE(e))) + { + can_change[xx][yy] = FALSE; + complete_change = FALSE; + } + } + + if (!change->only_complete || complete_change) + { + if (change->only_complete && change->use_random_change && + RND(change->random) != 0) + return; + + for (yy = 0; yy < 3; yy++) for(xx = 0; xx < 3 ; xx++) + { + int ex = x + xx - 1; + int ey = y + yy - 1; + + if (can_change[xx][yy] && (!change->use_random_change || + RND(change->random) == 0)) + { + ChangeElementNowExt(ex, ey, change->content[xx][yy]); + + /* for symmetry reasons, stop newly created border elements */ + if (ex != x || ey != y) + Stop[ex][ey] = TRUE; + } + } - DrawLevelField(xx, yy); + return; } } + + ChangeElementNowExt(x, y, change->target_element); } static void ChangeElement(int x, int y) { +#if 1 + int element = MovingOrBlocked2Element(x, y); +#else int element = Feld[x][y]; +#endif + struct ElementChangeInfo *change = &element_info[element].change; if (ChangeDelay[x][y] == 0) /* initialize element change */ { +#if 1 + ChangeDelay[x][y] = ( change->delay_fixed * change->delay_frames + + RND(change->delay_random * change->delay_frames)) + 1; +#else ChangeDelay[x][y] = changing_element[element].change_delay + 1; if (IS_CUSTOM_ELEMENT(element) && HAS_CHANGE_EVENT(element, CE_DELAY)) @@ -5002,12 +5186,18 @@ static void ChangeElement(int x, int y) ChangeDelay[x][y] += RND(max_random_delay * delay_frames); } +#endif ResetGfxAnimation(x, y); ResetRandomAnimationValue(x, y); +#if 1 + if (change->pre_change_function) + change->pre_change_function(x, y); +#else if (changing_element[element].pre_change_function) changing_element[element].pre_change_function(x, y); +#endif } ChangeDelay[x][y]--; @@ -5019,12 +5209,19 @@ static void ChangeElement(int x, int y) if (IS_ANIMATED(graphic)) DrawLevelGraphicAnimationIfNeeded(x, y, graphic); +#if 1 + if (change->change_function) + change->change_function(x, y); +#else if (changing_element[element].change_function) changing_element[element].change_function(x, y); +#endif } else /* finish element change */ { +#if 0 int next_element = changing_element[element].next_element; +#endif if (IS_MOVING(x, y)) /* never change a running system ;-) */ { @@ -5033,52 +5230,65 @@ static void ChangeElement(int x, int y) return; } +#if 1 + ChangeElementNow(x, y, element); + + if (change->post_change_function) + change->post_change_function(x, y); +#else if (next_element != EL_UNDEFINED) - ChangeElementDoIt(x, y, next_element); + ChangeElementNow(x, y, next_element); else - ChangeElementDoIt(x, y, element_info[element].change.successor); + ChangeElementNow(x, y, element_info[element].change.target_element); if (changing_element[element].post_change_function) changing_element[element].post_change_function(x, y); +#endif } } -static void CheckTriggeredElementChange(int trigger_element, int trigger_event) +static boolean CheckTriggeredElementChange(int lx, int ly, int trigger_element, + int trigger_event) { int i, x, y; if (!(trigger_events[trigger_element] & CH_EVENT_BIT(trigger_event))) - return; + return FALSE; for (i=0; iactive) RemoveHero(player); @@ -6109,6 +6320,75 @@ void ScrollScreen(struct PlayerInfo *player, int mode) ScreenMovDir = MV_NO_MOVING; } +void TestIfPlayerTouchesCustomElement(int x, int y) +{ + static int xy[4][2] = + { + { 0, -1 }, + { -1, 0 }, + { +1, 0 }, + { 0, +1 } + }; + boolean center_is_player = (IS_PLAYER(x, y)); + int i; + + for (i=0; i<4; i++) + { + int xx = x + xy[i][0]; + int yy = y + xy[i][1]; + + if (!IN_LEV_FIELD(xx, yy)) + continue; + + if (center_is_player) + { + CheckTriggeredElementChange(xx, yy, Feld[xx][yy], CE_OTHER_GETS_TOUCHED); + CheckElementChange(xx, yy, Feld[xx][yy], CE_TOUCHED_BY_PLAYER); + } + else if (IS_PLAYER(xx, yy)) + { + CheckTriggeredElementChange(x, y, Feld[x][y], CE_OTHER_GETS_TOUCHED); + CheckElementChange(x, y, Feld[x][y], CE_TOUCHED_BY_PLAYER); + + break; + } + } +} + +void TestIfElementTouchesCustomElement(int x, int y) +{ + static int xy[4][2] = + { + { 0, -1 }, + { -1, 0 }, + { +1, 0 }, + { 0, +1 } + }; + boolean center_is_custom = (IS_CUSTOM_ELEMENT(Feld[x][y])); + int i; + + for (i=0; i<4; i++) + { + int xx = x + xy[i][0]; + int yy = y + xy[i][1]; + + if (!IN_LEV_FIELD(xx, yy)) + continue; + + if (center_is_custom && + Feld[xx][yy] == element_info[Feld[x][y]].change.trigger_element) + { + CheckElementChange(x, y, Feld[x][y], CE_OTHER_IS_TOUCHING); + } + + if (IS_CUSTOM_ELEMENT(Feld[xx][yy]) && + Feld[x][y] == element_info[Feld[xx][yy]].change.trigger_element) + { + CheckElementChange(xx, yy, Feld[xx][yy], CE_OTHER_IS_TOUCHING); + } + } +} + void TestIfGoodThingHitsBadThing(int good_x, int good_y, int good_move_dir) { int i, kill_x = -1, kill_y = -1; @@ -6399,10 +6679,12 @@ void RemoveHero(struct PlayerInfo *player) } /* + ============================================================================= checkDiagonalPushing() ----------------------------------------------------------------------------- check if diagonal input device direction results in pushing of object (by checking if the alternative direction is walkable, diggable, ...) + ============================================================================= */ static boolean checkDiagonalPushing(struct PlayerInfo *player, @@ -6425,10 +6707,12 @@ static boolean checkDiagonalPushing(struct PlayerInfo *player, } /* + ============================================================================= DigField() ----------------------------------------------------------------------------- x, y: field next to player (non-diagonal) to try to dig to real_dx, real_dy: direction as read from input device (can be diagonal) + ============================================================================= */ int DigField(struct PlayerInfo *player, @@ -6437,6 +6721,7 @@ int DigField(struct PlayerInfo *player, boolean use_spring_bug = (game.engine_version < VERSION_IDENT(2,2,0)); int jx = player->jx, jy = player->jy; int dx = x - jx, dy = y - jy; + int nextx = x + dx, nexty = y + dy; int move_direction = (dx == -1 ? MV_LEFT : dx == +1 ? MV_RIGHT : dy == -1 ? MV_UP : @@ -6461,14 +6746,7 @@ int DigField(struct PlayerInfo *player, } if (IS_MOVING(x, y) || IS_PLAYER(x, y)) - { -#if 0 - if (FrameCounter == 437) - printf("::: ---> IS_MOVING %d\n", MovDir[x][y]); -#endif - return MF_NO_ACTION; - } #if 0 if (IS_TUBE(Feld[jx][jy]) || IS_TUBE(Back[jx][jy])) @@ -6508,227 +6786,12 @@ int DigField(struct PlayerInfo *player, element = Feld[x][y]; -#if 1 if (mode == DF_SNAP && !IS_SNAPPABLE(element) && game.engine_version >= VERSION_IDENT(2,2,0)) return MF_NO_ACTION; -#endif switch (element) { -#if 0 - case EL_EMPTY: - PlaySoundLevelElementAction(x, y, player->element_nr, ACTION_MOVING); - break; -#endif - -#if 0 - case EL_SAND: - case EL_INVISIBLE_SAND: - case EL_INVISIBLE_SAND_ACTIVE: - case EL_TRAP: - case EL_SP_BASE: - case EL_SP_BUGGY_BASE: - case EL_SP_BUGGY_BASE_ACTIVATING: - RemoveField(x, y); - - if (mode != DF_SNAP && element != EL_EMPTY) - { - GfxElement[x][y] = (CAN_BE_CRUMBLED(element) ? EL_SAND : element); - player->is_digging = TRUE; - } - - PlaySoundLevelElementAction(x, y, element, ACTION_DIGGING); - break; -#endif - - case EL_EMERALD: - case EL_BD_DIAMOND: - case EL_EMERALD_YELLOW: - case EL_EMERALD_RED: - case EL_EMERALD_PURPLE: - case EL_DIAMOND: - case EL_SP_INFOTRON: - case EL_PEARL: - case EL_CRYSTAL: - RemoveField(x, y); - - if (mode != DF_SNAP) - { - GfxElement[x][y] = element; - player->is_collecting = TRUE; - } - - local_player->gems_still_needed -= (element == EL_DIAMOND ? 3 : - element == EL_PEARL ? 5 : - element == EL_CRYSTAL ? 8 : 1); - if (local_player->gems_still_needed < 0) - local_player->gems_still_needed = 0; - RaiseScoreElement(element); - DrawText(DX_EMERALDS, DY_EMERALDS, - int2str(local_player->gems_still_needed, 3), FONT_TEXT_2); - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; - - case EL_SPEED_PILL: - RemoveField(x, y); - player->move_delay_value = MOVE_DELAY_HIGH_SPEED; -#if 1 - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); -#else - PlaySoundLevel(x, y, SND_SPEED_PILL_COLLECTING); -#endif - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; - -#if 0 - case EL_ENVELOPE: - Feld[x][y] = EL_EMPTY; -#if 1 - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); -#else - PlaySoundLevel(x, y, SND_ENVELOPE_COLLECTING); -#endif - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; -#endif - - case EL_EXTRA_TIME: - RemoveField(x, y); - if (level.time > 0) - { - TimeLeft += 10; - DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_TEXT_2); - } -#if 1 - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); -#else - PlaySoundStereo(SND_EXTRA_TIME_COLLECTING, SOUND_MIDDLE); -#endif - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; - - case EL_SHIELD_NORMAL: - RemoveField(x, y); - player->shield_normal_time_left += 10; -#if 1 - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); -#else - PlaySoundLevel(x, y, SND_SHIELD_NORMAL_COLLECTING); -#endif - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; - - case EL_SHIELD_DEADLY: - RemoveField(x, y); - player->shield_normal_time_left += 10; - player->shield_deadly_time_left += 10; -#if 1 - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); -#else - PlaySoundLevel(x, y, SND_SHIELD_DEADLY_COLLECTING); -#endif - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; - - case EL_DYNAMITE: - case EL_SP_DISK_RED: - RemoveField(x, y); - player->dynamite++; - player->use_disk_red_graphic = (element == EL_SP_DISK_RED); - RaiseScoreElement(EL_DYNAMITE); - DrawText(DX_DYNAMITE, DY_DYNAMITE, int2str(local_player->dynamite, 3), - FONT_TEXT_2); - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; - - case EL_DYNABOMB_INCREASE_NUMBER: - RemoveField(x, y); - player->dynabomb_count++; - player->dynabombs_left++; - RaiseScoreElement(EL_DYNAMITE); -#if 1 - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); -#else - PlaySoundLevel(x, y, SND_DYNABOMB_INCREASE_NUMBER_COLLECTING); -#endif - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; - - case EL_DYNABOMB_INCREASE_SIZE: - RemoveField(x, y); - player->dynabomb_size++; - RaiseScoreElement(EL_DYNAMITE); -#if 1 - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); -#else - PlaySoundLevel(x, y, SND_DYNABOMB_INCREASE_SIZE_COLLECTING); -#endif - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; - - case EL_DYNABOMB_INCREASE_POWER: - RemoveField(x, y); - player->dynabomb_xl = TRUE; - RaiseScoreElement(EL_DYNAMITE); -#if 1 - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); -#else - PlaySoundLevel(x, y, SND_DYNABOMB_INCREASE_POWER_COLLECTING); -#endif - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; - - case EL_KEY_1: - case EL_KEY_2: - case EL_KEY_3: - case EL_KEY_4: - { - int key_nr = element - EL_KEY_1; - int graphic = el2edimg(element); - - RemoveField(x, y); - player->key[key_nr] = TRUE; - RaiseScoreElement(element); - DrawMiniGraphicExt(drawto, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS, - graphic); - DrawMiniGraphicExt(window, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS, - graphic); -#if 1 - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); -#else - PlaySoundLevel(x, y, SND_CLASS_KEY_COLLECTING); -#endif - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; - } - - case EL_EM_KEY_1: - case EL_EM_KEY_2: - case EL_EM_KEY_3: - case EL_EM_KEY_4: - { - int key_nr = element - EL_EM_KEY_1; - int graphic = el2edimg(EL_KEY_1 + key_nr); - - RemoveField(x, y); - player->key[key_nr] = TRUE; - RaiseScoreElement(element); - DrawMiniGraphicExt(drawto, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS, - graphic); - DrawMiniGraphicExt(window, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS, - graphic); -#if 1 - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); -#else - PlaySoundLevel(x, y, SND_CLASS_KEY_COLLECTING); -#endif - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; - } - case EL_ROBOT_WHEEL: Feld[x][y] = EL_ROBOT_WHEEL_ACTIVE; ZX = x; @@ -6829,171 +6892,6 @@ int DigField(struct PlayerInfo *player, return MF_ACTION; break; -#if 0 - - /* the following elements cannot be pushed by "snapping" */ - case EL_ROCK: - case EL_BOMB: - case EL_DX_SUPABOMB: - case EL_NUT: - case EL_TIME_ORB_EMPTY: - case EL_SP_ZONK: - case EL_SP_DISK_ORANGE: - 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) - return MF_NO_ACTION; - - if (CAN_FALL(element) && IN_LEV_FIELD(x, y + 1) && IS_FREE(x, y + 1) && - !(element == EL_SPRING && use_spring_bug)) - return MF_NO_ACTION; - - player->Pushing = TRUE; - -#if 0 - if (element == EL_ROCK) - printf("::: wanna push [%d] [%d]\n", - FrameCounter, player->push_delay_value); -#endif - - if (!IN_LEV_FIELD(x+dx, y+dy) || !IS_FREE(x+dx, y+dy)) - return MF_NO_ACTION; - - if (!checkDiagonalPushing(player, x, y, real_dx, real_dy)) - return MF_NO_ACTION; - - - if (player->push_delay == 0) - player->push_delay = FrameCounter; - -#if 0 - printf("want push... %d [%d]\n", FrameCounter, player->push_delay_value); -#endif - -#if 0 - if (!FrameReached(&player->push_delay, player->push_delay_value) && - !tape.playing && - element != EL_SPRING) - return MF_NO_ACTION; -#else - if (!FrameReached(&player->push_delay, player->push_delay_value) && - !(tape.playing && tape.file_version < FILE_VERSION_2_0) && - element != EL_SPRING) - return MF_NO_ACTION; -#endif - - if (mode == DF_SNAP) - { - InitMovingField(x, y, move_direction); - ContinueMoving(x, y); - } - else - { -#if 1 - InitMovingField(x, y, (dx < 0 ? MV_LEFT : - dx > 0 ? MV_RIGHT : - dy < 0 ? MV_UP : MV_DOWN)); - MovPos[x][y] = (dx != 0 ? dx : dy); -#else - RemoveField(x, y); - Feld[x + dx][y + dy] = element; -#endif - } - -#if 0 - printf("pushing %d/%d ... %d [%d]\n", dx, dy, - FrameCounter, player->push_delay_value); -#endif - -#if 0 - if (element == EL_SPRING) - { - Feld[x + dx][y + dy] = EL_SPRING; - MovDir[x + dx][y + dy] = move_direction; - } -#endif - - player->push_delay_value = (element == EL_SPRING ? 0 : 2 + RND(8)); - - DrawLevelField(x + dx, y + dy); - PlaySoundLevelElementAction(x, y, element, ACTION_PUSHING); - - CheckTriggeredElementChange(element, CE_OTHER_PUSHING); - - break; - -#endif - - case EL_GATE_1: - case EL_GATE_2: - case EL_GATE_3: - case EL_GATE_4: - if (!player->key[element - EL_GATE_1]) - return MF_NO_ACTION; - break; - - case EL_GATE_1_GRAY: - case EL_GATE_2_GRAY: - case EL_GATE_3_GRAY: - case EL_GATE_4_GRAY: - if (!player->key[element - EL_GATE_1_GRAY]) - return MF_NO_ACTION; - break; - - case EL_EM_GATE_1: - case EL_EM_GATE_2: - case EL_EM_GATE_3: - case EL_EM_GATE_4: - if (!player->key[element - EL_EM_GATE_1]) - return MF_NO_ACTION; - if (!IN_LEV_FIELD(x + dx, y + dy) || !IS_FREE(x + dx, y + dy)) - return MF_NO_ACTION; - - /* automatically move to the next field with double speed */ - player->programmed_action = move_direction; - DOUBLE_PLAYER_SPEED(player); - - PlaySoundLevel(x, y, SND_CLASS_GATE_PASSING); - break; - - case EL_EM_GATE_1_GRAY: - case EL_EM_GATE_2_GRAY: - case EL_EM_GATE_3_GRAY: - case EL_EM_GATE_4_GRAY: - if (!player->key[element - EL_EM_GATE_1_GRAY]) - return MF_NO_ACTION; - if (!IN_LEV_FIELD(x + dx, y + dy) || !IS_FREE(x + dx, y + dy)) - return MF_NO_ACTION; - - /* automatically move to the next field with double speed */ - player->programmed_action = move_direction; - DOUBLE_PLAYER_SPEED(player); - -#if 1 - PlaySoundLevelAction(x, y, ACTION_PASSING); -#else - PlaySoundLevel(x, y, SND_GATE_PASSING); -#endif - break; - - case EL_SWITCHGATE_OPEN: - case EL_TIMEGATE_OPEN: - if (!IN_LEV_FIELD(x + dx, y + dy) || !IS_FREE(x + dx, y + dy)) - return MF_NO_ACTION; - - /* automatically move to the next field with double speed */ - player->programmed_action = move_direction; - DOUBLE_PLAYER_SPEED(player); - - PlaySoundLevelElementAction(x, y, element, ACTION_PASSING); - break; - case EL_SP_PORT_LEFT: case EL_SP_PORT_RIGHT: case EL_SP_PORT_UP: @@ -7025,8 +6923,8 @@ int DigField(struct PlayerInfo *player, element != EL_SP_GRAVITY_PORT_DOWN && element != EL_SP_PORT_VERTICAL && element != EL_SP_PORT_ANY) || - !IN_LEV_FIELD(x + dx, y + dy) || - !IS_FREE(x + dx, y + dy)) + !IN_LEV_FIELD(nextx, nexty) || + !IS_FREE(nextx, nexty)) return MF_NO_ACTION; /* automatically move to the next field with double speed */ @@ -7075,28 +6973,10 @@ int DigField(struct PlayerInfo *player, if (!(tube_enter_directions[i][1] & move_direction)) return MF_NO_ACTION; /* tube has no opening in this direction */ - PlaySoundLevel(x, y, SND_CLASS_TUBE_PASSING); + PlaySoundLevel(x, y, SND_CLASS_TUBE_WALKING); } break; - case EL_EXIT_CLOSED: - case EL_SP_EXIT_CLOSED: - case EL_EXIT_OPENING: - return MF_NO_ACTION; - break; - - case EL_EXIT_OPEN: - case EL_SP_EXIT_OPEN: - if (mode == DF_SNAP) - return MF_NO_ACTION; - - if (element == EL_EXIT_OPEN) - PlaySoundLevel(x, y, SND_CLASS_EXIT_PASSING); - else - PlaySoundLevel(x, y, SND_CLASS_SP_EXIT_PASSING); - - break; - case EL_LAMP: Feld[x][y] = EL_LAMP_ACTIVE; local_player->lights_still_needed--; @@ -7114,171 +6994,61 @@ int DigField(struct PlayerInfo *player, return MF_ACTION; break; -#if 0 - -#if 0 - case EL_SOKOBAN_FIELD_EMPTY: - break; -#endif - - case EL_SOKOBAN_OBJECT: - case EL_SOKOBAN_FIELD_FULL: - case EL_SATELLITE: - case EL_SP_DISK_YELLOW: - case EL_BALLOON: - if (mode == DF_SNAP) - return MF_NO_ACTION; - - player->Pushing = TRUE; - - if (!IN_LEV_FIELD(x+dx, y+dy) - || (!IS_FREE(x+dx, y+dy) - && (Feld[x+dx][y+dy] != EL_SOKOBAN_FIELD_EMPTY - || !IS_SB_ELEMENT(element)))) - return MF_NO_ACTION; - - if (!checkDiagonalPushing(player, x, y, real_dx, real_dy)) - return MF_NO_ACTION; - - if (player->push_delay == 0) - player->push_delay = FrameCounter; -#if 0 - if (!FrameReached(&player->push_delay, player->push_delay_value) && - !tape.playing && element != EL_BALLOON) - return MF_NO_ACTION; -#else - if (!FrameReached(&player->push_delay, player->push_delay_value) && - !(tape.playing && tape.file_version < FILE_VERSION_2_0) && - element != EL_BALLOON) - return MF_NO_ACTION; -#endif + default: - if (IS_SB_ELEMENT(element)) + if (IS_WALKABLE(element)) { -#if 1 - if (element == EL_SOKOBAN_FIELD_FULL) - { - Back[x][y] = EL_SOKOBAN_FIELD_EMPTY; - local_player->sokobanfields_still_needed++; - } + int sound_action = ACTION_WALKING; - if (Feld[x + dx][y + dy] == EL_SOKOBAN_FIELD_EMPTY) + if (element >= EL_GATE_1 && element <= EL_GATE_4) { - Back[x + dx][y + dy] = EL_SOKOBAN_FIELD_EMPTY; - local_player->sokobanfields_still_needed--; + if (!player->key[element - EL_GATE_1]) + return MF_NO_ACTION; } - - Feld[x][y] = EL_SOKOBAN_OBJECT; - - if (Back[x][y] == Back[x + dx][y + dy]) - PlaySoundLevelAction(x, y, ACTION_PUSHING); - else if (Back[x][y] != 0) - PlaySoundLevelElementAction(x, y, EL_SOKOBAN_FIELD_FULL, - ACTION_EMPTYING); - else - PlaySoundLevelElementAction(x + dx, y + dy, EL_SOKOBAN_FIELD_EMPTY, - ACTION_FILLING); - - InitMovingField(x, y, (dx < 0 ? MV_LEFT : - dx > 0 ? MV_RIGHT : - dy < 0 ? MV_UP : MV_DOWN)); - MovPos[x][y] = (dx != 0 ? dx : dy); - -#if 0 - printf("::: %s -> %s [%s -> %s]\n", - element_info[Feld[x][y]].token_name, - element_info[Feld[x + dx][y + dy]].token_name, - element_info[Back[x][y]].token_name, - element_info[Back[x + dx][y + dy]].token_name); -#endif - -#else - if (element == EL_SOKOBAN_FIELD_FULL) + else if (element >= EL_GATE_1_GRAY && element <= EL_GATE_4_GRAY) { - Feld[x][y] = EL_SOKOBAN_FIELD_EMPTY; - local_player->sokobanfields_still_needed++; + if (!player->key[element - EL_GATE_1_GRAY]) + return MF_NO_ACTION; } - else - RemoveField(x, y); - - if (Feld[x+dx][y+dy] == EL_SOKOBAN_FIELD_EMPTY) + else if (element == EL_EXIT_OPEN || element == EL_SP_EXIT_OPEN) { - Feld[x+dx][y+dy] = EL_SOKOBAN_FIELD_FULL; - local_player->sokobanfields_still_needed--; - if (element == EL_SOKOBAN_OBJECT) -#if 1 - PlaySoundLevelAction(x+dx, y+dy, ACTION_FILLING); -#else - PlaySoundLevel(x, y, SND_CLASS_SOKOBAN_FIELD_FILLING); -#endif - else -#if 1 - PlaySoundLevelAction(x+dx, y+dy, ACTION_PUSHING); -#else - PlaySoundLevel(x, y, SND_SOKOBAN_OBJECT_PUSHING); -#endif + sound_action = ACTION_PASSING; /* player is passing exit */ } - else + else if (element == EL_EMPTY) { - Feld[x+dx][y+dy] = EL_SOKOBAN_OBJECT; - if (element == EL_SOKOBAN_FIELD_FULL) -#if 1 - PlaySoundLevelAction(x+dx, y+dy, ACTION_EMPTYING); -#else - PlaySoundLevel(x, y, SND_SOKOBAN_FIELD_EMPTYING); -#endif - else -#if 1 - PlaySoundLevelAction(x+dx, y+dy, ACTION_PUSHING); -#else - PlaySoundLevel(x, y, SND_SOKOBAN_OBJECT_PUSHING); -#endif + sound_action = ACTION_MOVING; /* nothing to walk on */ } -#endif - } - else - { -#if 1 - InitMovingField(x, y, (dx < 0 ? MV_LEFT : - dx > 0 ? MV_RIGHT : - dy < 0 ? MV_UP : MV_DOWN)); - MovPos[x][y] = (dx != 0 ? dx : dy); -#else - RemoveField(x, y); - Feld[x + dx][y + dy] = element; -#endif - PlaySoundLevelElementAction(x, y, element, ACTION_PUSHING); - } - player->push_delay_value = (element == EL_BALLOON ? 0 : 2); - - DrawLevelField(x, y); - DrawLevelField(x + dx, y + dy); + /* play sound from background or player, whatever is available */ + if (element_info[element].sound[sound_action] != SND_UNDEFINED) + PlaySoundLevelElementAction(x, y, element, sound_action); + else + PlaySoundLevelElementAction(x, y, player->element_nr, sound_action); - if (IS_SB_ELEMENT(element) && - local_player->sokobanfields_still_needed == 0 && - game.emulation == EMU_SOKOBAN) - { - player->LevelSolved = player->GameOver = TRUE; - PlaySoundLevel(x, y, SND_GAME_SOKOBAN_SOLVING); + break; } + else if (IS_PASSABLE(element)) + { + if (!IN_LEV_FIELD(nextx, nexty) || !IS_FREE(nextx, nexty)) + return MF_NO_ACTION; - CheckTriggeredElementChange(element, CE_OTHER_PUSHING); + if (element >= EL_EM_GATE_1 && element <= EL_EM_GATE_4) + { + if (!player->key[element - EL_EM_GATE_1]) + return MF_NO_ACTION; + } + else if (element >= EL_EM_GATE_1_GRAY && element <= EL_EM_GATE_4_GRAY) + { + if (!player->key[element - EL_EM_GATE_1_GRAY]) + return MF_NO_ACTION; + } - break; + /* automatically move to the next field with double speed */ + player->programmed_action = move_direction; + DOUBLE_PLAYER_SPEED(player); -#endif + PlaySoundLevelAction(x, y, ACTION_PASSING); - case EL_PENGUIN: - case EL_PIG: - case EL_DRAGON: - break; - - default: - - if (IS_WALKABLE(element)) - { - PlaySoundLevelElementAction(x, y, player->element_nr, ACTION_MOVING); break; } else if (IS_DIGGABLE(element)) @@ -7306,11 +7076,67 @@ int DigField(struct PlayerInfo *player, player->is_collecting = TRUE; } - RaiseScoreElement(element); + if (element == EL_SPEED_PILL) + player->move_delay_value = MOVE_DELAY_HIGH_SPEED; + else if (element == EL_EXTRA_TIME && level.time > 0) + { + TimeLeft += 10; + DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_TEXT_2); + } + else if (element == EL_SHIELD_NORMAL || element == EL_SHIELD_DEADLY) + { + player->shield_normal_time_left += 10; + if (element == EL_SHIELD_DEADLY) + player->shield_deadly_time_left += 10; + } + else if (element == EL_DYNAMITE || element == EL_SP_DISK_RED) + { + player->dynamite++; + player->use_disk_red_graphic = (element == EL_SP_DISK_RED); + DrawText(DX_DYNAMITE, DY_DYNAMITE, + int2str(local_player->dynamite, 3), FONT_TEXT_2); + } + else if (element == EL_DYNABOMB_INCREASE_NUMBER) + { + player->dynabomb_count++; + player->dynabombs_left++; + } + else if (element == EL_DYNABOMB_INCREASE_SIZE) + { + player->dynabomb_size++; + } + else if (element == EL_DYNABOMB_INCREASE_POWER) + { + player->dynabomb_xl = TRUE; + } + else if ((element >= EL_KEY_1 && element <= EL_KEY_4) || + (element >= EL_EM_KEY_1 && element <= EL_EM_KEY_4)) + { + int key_nr = (element >= EL_KEY_1 && element <= EL_KEY_4 ? + element - EL_KEY_1 : element - EL_EM_KEY_1); + + player->key[key_nr] = TRUE; + + DrawMiniGraphicExt(drawto, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS, + el2edimg(EL_KEY_1 + key_nr)); + redraw_mask |= REDRAW_DOOR_1; + } + else if (element_info[element].gem_count > 0) + { + local_player->gems_still_needed -= + element_info[element].gem_count; + if (local_player->gems_still_needed < 0) + local_player->gems_still_needed = 0; + + DrawText(DX_EMERALDS, DY_EMERALDS, + int2str(local_player->gems_still_needed, 3), FONT_TEXT_2); + } + + RaiseScoreElement(element); PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); + CheckTriggeredElementChange(x, y, element, CE_OTHER_GETS_COLLECTED); break; } @@ -7335,9 +7161,9 @@ int DigField(struct PlayerInfo *player, player->Pushing = TRUE; - if (!(IN_LEV_FIELD(x + dx, y + dy) && - (IS_FREE(x + dx, y + dy) || - (Feld[x + dx][y + dy] == EL_SOKOBAN_FIELD_EMPTY && + if (!(IN_LEV_FIELD(nextx, nexty) && + (IS_FREE(nextx, nexty) || + (Feld[nextx][nexty] == EL_SOKOBAN_FIELD_EMPTY && IS_SB_ELEMENT(element))))) return MF_NO_ACTION; @@ -7360,21 +7186,21 @@ int DigField(struct PlayerInfo *player, local_player->sokobanfields_still_needed++; } - if (Feld[x + dx][y + dy] == EL_SOKOBAN_FIELD_EMPTY) + if (Feld[nextx][nexty] == EL_SOKOBAN_FIELD_EMPTY) { - Back[x + dx][y + dy] = EL_SOKOBAN_FIELD_EMPTY; + Back[nextx][nexty] = EL_SOKOBAN_FIELD_EMPTY; local_player->sokobanfields_still_needed--; } Feld[x][y] = EL_SOKOBAN_OBJECT; - if (Back[x][y] == Back[x + dx][y + dy]) + if (Back[x][y] == Back[nextx][nexty]) PlaySoundLevelAction(x, y, ACTION_PUSHING); else if (Back[x][y] != 0) PlaySoundLevelElementAction(x, y, EL_SOKOBAN_FIELD_FULL, ACTION_EMPTYING); else - PlaySoundLevelElementAction(x + dx, y + dy, EL_SOKOBAN_FIELD_EMPTY, + PlaySoundLevelElementAction(nextx, nexty, EL_SOKOBAN_FIELD_EMPTY, ACTION_FILLING); if (local_player->sokobanfields_still_needed == 0 && @@ -7395,19 +7221,20 @@ int DigField(struct PlayerInfo *player, MovPos[x][y] = (dx != 0 ? dx : dy); Pushed[x][y] = TRUE; - Pushed[x + dx][y + dy] = TRUE; + Pushed[nextx][nexty] = TRUE; if (game.engine_version < RELEASE_IDENT(2,2,0,7)) player->push_delay_value = GET_NEW_PUSH_DELAY(element); - CheckTriggeredElementChange(element, CE_OTHER_PUSHING); - CheckPlayerElementChange(x, y, element, CE_PUSHED_BY_PLAYER); + CheckTriggeredElementChange(x, y, element, CE_OTHER_GETS_PUSHED); + CheckElementChange(x, y, element, CE_PUSHED_BY_PLAYER); break; } else { - CheckPlayerElementChange(x, y, element, CE_PRESSED_BY_PLAYER); + CheckTriggeredElementChange(x, y, element, CE_OTHER_GETS_PRESSED); + CheckElementChange(x, y, element, CE_PRESSED_BY_PLAYER); } return MF_NO_ACTION; @@ -7425,6 +7252,10 @@ boolean SnapField(struct PlayerInfo *player, int dx, int dy) { int jx = player->jx, jy = player->jy; int x = jx + dx, y = jy + dy; + int snap_direction = (dx == -1 ? MV_LEFT : + dx == +1 ? MV_RIGHT : + dy == -1 ? MV_UP : + dy == +1 ? MV_DOWN : MV_NO_MOVING); if (player->MovPos && game.engine_version >= VERSION_IDENT(2,2,0)) return FALSE; @@ -7454,10 +7285,7 @@ boolean SnapField(struct PlayerInfo *player, int dx, int dy) if (player->snapped) return FALSE; - player->MovDir = (dx < 0 ? MV_LEFT : - dx > 0 ? MV_RIGHT : - dy < 0 ? MV_UP : - dy > 0 ? MV_DOWN : MV_NO_MOVING); + player->MovDir = snap_direction; if (DigField(player, x, y, 0, 0, DF_SNAP) == MF_NO_ACTION) return FALSE; @@ -7697,6 +7525,7 @@ void RaiseScoreElement(int element) RaiseScore(level.score[SC_NUT]); break; case EL_DYNAMITE: + case EL_SP_DISK_RED: case EL_DYNABOMB_INCREASE_NUMBER: case EL_DYNABOMB_INCREASE_SIZE: case EL_DYNABOMB_INCREASE_POWER: