X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=3051f5ac9d93771620536c019413d08420dceec0;hb=9de8eede744c45187c7011543ef8097d1ebc879c;hp=745407c990f1585a45408baf08f94fa302b6bf47;hpb=ba1b0c1eeb801aa66ab68bb57fb6cbe08f8a9689;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 745407c9..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); @@ -370,6 +376,25 @@ push_delay_list[] = { 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; @@ -377,28 +402,26 @@ struct } 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 }, + { 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 struct ChangingElementInfo changing_element[MAX_NUM_ELEMENTS]; +static boolean changing_element[MAX_NUM_ELEMENTS]; static unsigned long trigger_events[MAX_NUM_ELEMENTS]; -static int gem_count[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() @@ -743,42 +766,75 @@ static void InitGameEngine() /* 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; +#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 ---------------------------------- */ @@ -790,7 +846,7 @@ static void InitGameEngine() /* add trigger events from element change event properties */ for (i=0; iPushing && player->MovPos != 0); -#else - boolean pushing = (player != NULL && player->Pushing && player->is_moving); -#endif -#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; -#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) /* special case: moving object pushed by player */ -#else - if (pushing) /* special case: moving object pushed by player */ -#endif -#if 1 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 */ { @@ -3957,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]; @@ -4055,7 +4111,6 @@ 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)) @@ -4077,20 +4132,14 @@ void ContinueMoving(int x, int y) (CAN_FALL(element) && MovDir[newx][newy] == MV_DOWN)) MovDir[newx][newy] = 0; #endif - -#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 + Stop[newx][newy] = TRUE; /* ignore this element until the next frame */ + if (!pushed) /* special case: moving object pushed by player */ -#endif JustStopped[newx][newy] = 3; if (DONT_TOUCH(element)) /* object may be nasty to player or others */ @@ -4102,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 */ { @@ -5002,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); @@ -5019,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; + } + + if (change->use_content) + { + boolean complete_change = TRUE; + boolean can_change[3][3]; + int xx, yy; - for(i=0; i<4; i++) + 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 */ - if (!IN_LEV_FIELD(xx, yy) || - !IN_SCR_FIELD(sxx, syy) || - !CAN_BE_CRUMBLED(Feld[xx][yy]) || - IS_MOVING(xx, yy)) continue; + } + + if (!IN_LEV_FIELD(ex, ey)) + { + can_change[xx][yy] = FALSE; + complete_change = FALSE; + + 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)) @@ -5063,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]--; @@ -5080,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 ;-) */ { @@ -5094,31 +5230,42 @@ 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); @@ -6170,38 +6320,107 @@ void ScrollScreen(struct PlayerInfo *player, int mode) ScreenMovDir = MV_NO_MOVING; } -void TestIfGoodThingHitsBadThing(int good_x, int good_y, int good_move_dir) +void TestIfPlayerTouchesCustomElement(int x, int y) { - int i, kill_x = -1, kill_y = -1; - static int test_xy[4][2] = + static int xy[4][2] = { { 0, -1 }, { -1, 0 }, { +1, 0 }, { 0, +1 } }; - static int test_dir[4] = - { - MV_UP, - MV_LEFT, - MV_RIGHT, - MV_DOWN - }; + boolean center_is_player = (IS_PLAYER(x, y)); + int i; for (i=0; i<4; i++) { - int test_x, test_y, test_move_dir, test_element; + int xx = x + xy[i][0]; + int yy = y + xy[i][1]; - test_x = good_x + test_xy[i][0]; - test_y = good_y + test_xy[i][1]; - if (!IN_LEV_FIELD(test_x, test_y)) + if (!IN_LEV_FIELD(xx, yy)) continue; - test_move_dir = - (IS_MOVING(test_x, test_y) ? MovDir[test_x][test_y] : MV_NO_MOVING); + 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); -#if 0 - test_element = Feld[test_x][test_y]; + 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; + static int test_xy[4][2] = + { + { 0, -1 }, + { -1, 0 }, + { +1, 0 }, + { 0, +1 } + }; + static int test_dir[4] = + { + MV_UP, + MV_LEFT, + MV_RIGHT, + MV_DOWN + }; + + for (i=0; i<4; i++) + { + int test_x, test_y, test_move_dir, test_element; + + test_x = good_x + test_xy[i][0]; + test_y = good_y + test_xy[i][1]; + if (!IN_LEV_FIELD(test_x, test_y)) + continue; + + test_move_dir = + (IS_MOVING(test_x, test_y) ? MovDir[test_x][test_y] : MV_NO_MOVING); + +#if 0 + test_element = Feld[test_x][test_y]; #else test_element = MovingOrBlocked2ElementIfNotLeaving(test_x, test_y); #endif @@ -6460,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, @@ -6486,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, @@ -6563,248 +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 - -#if 0 - - 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; - -#endif - -#if 0 - - 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; - -#endif - - -#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 - -#if 0 - - 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; - -#endif - -#if 0 - 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; -#endif - -#if 0 - 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; -#endif - -#if 0 - 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; -#endif - -#if 0 - 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; - } -#endif - case EL_ROBOT_WHEEL: Feld[x][y] = EL_ROBOT_WHEEL_ACTIVE; ZX = x; @@ -6905,175 +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 - -#if 0 - 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; -#endif - -#if 0 - 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; -#endif - case EL_SP_PORT_LEFT: case EL_SP_PORT_RIGHT: case EL_SP_PORT_UP: @@ -7159,28 +6977,6 @@ int DigField(struct PlayerInfo *player, } break; -#if 0 - case EL_EXIT_CLOSED: - case EL_SP_EXIT_CLOSED: - case EL_EXIT_OPENING: - return MF_NO_ACTION; - break; -#endif - -#if 0 - 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; -#endif - case EL_LAMP: Feld[x][y] = EL_LAMP_ACTIVE; local_player->lights_still_needed--; @@ -7198,168 +6994,6 @@ 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 - - if (IS_SB_ELEMENT(element)) - { -#if 1 - if (element == EL_SOKOBAN_FIELD_FULL) - { - Back[x][y] = EL_SOKOBAN_FIELD_EMPTY; - local_player->sokobanfields_still_needed++; - } - - if (Feld[x + dx][y + dy] == EL_SOKOBAN_FIELD_EMPTY) - { - Back[x + dx][y + dy] = EL_SOKOBAN_FIELD_EMPTY; - local_player->sokobanfields_still_needed--; - } - - 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) - { - Feld[x][y] = EL_SOKOBAN_FIELD_EMPTY; - local_player->sokobanfields_still_needed++; - } - else - RemoveField(x, y); - - if (Feld[x+dx][y+dy] == EL_SOKOBAN_FIELD_EMPTY) - { - 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 - } - else - { - 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 - } -#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); - - 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); - } - - CheckTriggeredElementChange(element, CE_OTHER_PUSHING); - - break; - -#endif - -#if 0 - case EL_PENGUIN: - case EL_PIG: - case EL_DRAGON: - break; -#endif - default: if (IS_WALKABLE(element)) @@ -7488,9 +7122,10 @@ int DigField(struct PlayerInfo *player, el2edimg(EL_KEY_1 + key_nr)); redraw_mask |= REDRAW_DOOR_1; } - else if (gem_count[element] > 0) + else if (element_info[element].gem_count > 0) { - local_player->gems_still_needed -= gem_count[element]; + local_player->gems_still_needed -= + element_info[element].gem_count; if (local_player->gems_still_needed < 0) local_player->gems_still_needed = 0; @@ -7501,7 +7136,7 @@ int DigField(struct PlayerInfo *player, RaiseScoreElement(element); PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); + CheckTriggeredElementChange(x, y, element, CE_OTHER_GETS_COLLECTED); break; } @@ -7591,14 +7226,15 @@ int DigField(struct PlayerInfo *player, 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;