X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=a67f9def973370667b5e45266cbfd76c70ecb4fd;hb=ad15815ec04f42779d0717a6d291f93b8e847d39;hp=3b06f4856fb2cb11b508431468892ff008dde8f8;hpb=bcf0b6f2f2fbcb33be313cbfffeabe64b1aa58d0;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 3b06f485..a67f9def 100644 --- a/src/game.c +++ b/src/game.c @@ -251,6 +251,22 @@ static struct ChangingElementInfo change_delay_list[] = NULL, NULL }, + { + EL_SP_EXIT_OPENING, + EL_SP_EXIT_OPEN, + 29, + NULL, + NULL, + NULL + }, + { + EL_SP_EXIT_CLOSING, + EL_SP_EXIT_CLOSED, + 29, + NULL, + NULL, + NULL + }, { EL_SWITCHGATE_OPENING, EL_SWITCHGATE_OPEN, @@ -1016,6 +1032,9 @@ void InitGame() player->Frame = 0; player->StepFrame = 0; + player->switch_x = -1; + player->switch_y = -1; + player->use_murphy_graphic = FALSE; player->use_disk_red_graphic = FALSE; @@ -1083,6 +1102,7 @@ void InitGame() game.timegate_time_left = 0; game.switchgate_pos = 0; game.balloon_dir = MV_NO_MOVING; + game.gravity = level.initial_gravity; game.explosions_delayed = TRUE; game.envelope_active = FALSE; @@ -1668,11 +1688,15 @@ void GameWon() } /* close exit door after last player */ - if (Feld[ExitX][ExitY] == EL_EXIT_OPEN && AllPlayersGone) + if ((Feld[ExitX][ExitY] == EL_EXIT_OPEN || + Feld[ExitX][ExitY] == EL_SP_EXIT_OPEN) && AllPlayersGone) { - Feld[ExitX][ExitY] = EL_EXIT_CLOSING; + int element = Feld[ExitX][ExitY]; - PlaySoundLevelElementAction(ExitX, ExitY, EL_EXIT_OPEN, ACTION_CLOSING); + Feld[ExitX][ExitY] = (element == EL_EXIT_OPEN ? EL_EXIT_CLOSING : + EL_SP_EXIT_CLOSING); + + PlaySoundLevelElementAction(ExitX, ExitY, element, ACTION_CLOSING); } /* Hero disappears */ @@ -2479,7 +2503,11 @@ void Bang(int x, int y) int element = Feld[x][y]; #endif +#if 1 + if (IS_PLAYER(x, y) && !PLAYER_PROTECTED(x, y)) +#else if (IS_PLAYER(x, y)) +#endif { struct PlayerInfo *player = PLAYERINFO(x, y); @@ -3091,6 +3119,11 @@ void Impact(int x, int y) else { CheckElementChange(x, y + 1, smashed, CE_SMASHED); + + CheckTriggeredElementSideChange(x, y + 1, smashed, CH_SIDE_TOP, + CE_OTHER_IS_SWITCHING); + CheckElementSideChange(x, y + 1, smashed, CH_SIDE_TOP, + CE_SWITCHED, -1); } } else @@ -4224,6 +4257,11 @@ void StartMoving(int x, int y) element1 != EL_DRAGON && element2 != EL_DRAGON && element1 != EL_FLAMES && element2 != EL_FLAMES) { +#if 1 + ResetGfxAnimation(x, y); + GfxAction[x][y] = ACTION_ATTACKING; +#endif + if (IS_PLAYER(x, y)) DrawPlayerField(x, y); else @@ -4237,6 +4275,7 @@ void StartMoving(int x, int y) Feld[newx1][newy1] = EL_FLAMES; if (IN_LEV_FIELD(newx2, newy2) && Feld[newx2][newy2] == EL_EMPTY) Feld[newx2][newy2] = EL_FLAMES; + return; } } @@ -4491,6 +4530,12 @@ void ContinueMoving(int x, int y) Stop[newx][newy] = TRUE; /* ignore this element until the next frame */ + /* prevent pushed element from moving on in pushed direction */ + if (pushed && CAN_MOVE(element) && + element_info[element].move_pattern & MV_ANY_DIRECTION && + !(element_info[element].move_pattern & MovDir[newx][newy])) + TurnRound(newx, newy); + if (!pushed) /* special case: moving object pushed by player */ JustStopped[newx][newy] = 3; @@ -5076,7 +5121,10 @@ void CheckExitSP(int x, int y) return; } - Feld[x][y] = EL_SP_EXIT_OPEN; + if (AllPlayersGone) /* do not re-open exit door closed after last player */ + return; + + Feld[x][y] = EL_SP_EXIT_OPENING; PlaySoundLevelNearest(x, y, SND_CLASS_SP_EXIT_OPENING); } @@ -5545,6 +5593,8 @@ static boolean ChangeElementNow(int x, int y, int element, int page) if (IS_MOVING(ex, ey) || IS_BLOCKED(ex, ey)) RemoveMovingField(ex, ey); + ChangeEvent[ex][ey] = ChangeEvent[x][y]; + ChangeElementNowExt(ex, ey, change->content[xx][yy]); something_has_changed = TRUE; @@ -6238,7 +6288,7 @@ void GameActions() } } - if (TimeFrames >= (1000 / GameFrameDelay)) + if (TimeFrames >= FRAMES_PER_SECOND) { TimeFrames = 0; TimePlayed++; @@ -6405,7 +6455,7 @@ void ScrollLevel(int dx, int dy) static void CheckGravityMovement(struct PlayerInfo *player) { - if (level.gravity && !player->programmed_action) + if (game.gravity && !player->programmed_action) { int move_dir_vertical = player->action & (MV_UP | MV_DOWN); int move_dir_horizontal = player->action & (MV_LEFT | MV_RIGHT); @@ -6696,6 +6746,10 @@ boolean MoveFigure(struct PlayerInfo *player, int dx, int dy) #if 1 player->snapped = FALSE; #endif + +#if 1 + player->Switching = FALSE; +#endif } else { @@ -6770,13 +6824,14 @@ void ScrollFigure(struct PlayerInfo *player, int mode) player->last_jy = jy; if (Feld[jx][jy] == EL_EXIT_OPEN || - Feld[jx][jy] == EL_SP_EXIT_OPEN) + Feld[jx][jy] == EL_SP_EXIT_OPEN || + Feld[jx][jy] == EL_SP_EXIT_OPENING) /* <-- special case */ { DrawPlayer(player); /* needed here only to cleanup last field */ RemoveHero(player); if (local_player->friends_still_needed == 0 || - Feld[jx][jy] == EL_SP_EXIT_OPEN) + IS_SP_ELEMENT(Feld[jx][jy])) player->LevelSolved = player->GameOver = TRUE; } @@ -7399,6 +7454,7 @@ int DigField(struct PlayerInfo *player, switch (element) { +#if 0 case EL_ROBOT_WHEEL: Feld[x][y] = EL_ROBOT_WHEEL_ACTIVE; ZX = x; @@ -7407,7 +7463,9 @@ int DigField(struct PlayerInfo *player, PlaySoundLevel(x, y, SND_ROBOT_WHEEL_ACTIVATING); return MF_ACTION; break; +#endif +#if 0 case EL_SP_TERMINAL: { int xx, yy; @@ -7428,7 +7486,9 @@ int DigField(struct PlayerInfo *player, return MF_ACTION; } break; +#endif +#if 0 case EL_CONVEYOR_BELT_1_SWITCH_LEFT: case EL_CONVEYOR_BELT_1_SWITCH_MIDDLE: case EL_CONVEYOR_BELT_1_SWITCH_RIGHT: @@ -7441,31 +7501,56 @@ int DigField(struct PlayerInfo *player, case EL_CONVEYOR_BELT_4_SWITCH_LEFT: case EL_CONVEYOR_BELT_4_SWITCH_MIDDLE: case EL_CONVEYOR_BELT_4_SWITCH_RIGHT: +#if 1 + if (!PLAYER_SWITCHING(player, x, y)) +#else if (!player->Switching) +#endif { player->Switching = TRUE; + player->switch_x = x; + player->switch_y = y; + ToggleBeltSwitch(x, y); PlaySoundLevel(x, y, SND_CLASS_CONVEYOR_BELT_SWITCH_ACTIVATING); } return MF_ACTION; break; +#endif +#if 0 case EL_SWITCHGATE_SWITCH_UP: case EL_SWITCHGATE_SWITCH_DOWN: +#if 1 + if (!PLAYER_SWITCHING(player, x, y)) +#else if (!player->Switching) +#endif { player->Switching = TRUE; + player->switch_x = x; + player->switch_y = y; + ToggleSwitchgateSwitch(x, y); PlaySoundLevel(x, y, SND_CLASS_SWITCHGATE_SWITCH_ACTIVATING); } return MF_ACTION; break; +#endif +#if 0 case EL_LIGHT_SWITCH: case EL_LIGHT_SWITCH_ACTIVE: +#if 1 + if (!PLAYER_SWITCHING(player, x, y)) +#else if (!player->Switching) +#endif { player->Switching = TRUE; + player->switch_x = x; + player->switch_y = y; + ToggleLightSwitch(x, y); PlaySoundLevel(x, y, element == EL_LIGHT_SWITCH ? SND_LIGHT_SWITCH_ACTIVATING : @@ -7473,14 +7558,18 @@ int DigField(struct PlayerInfo *player, } return MF_ACTION; break; +#endif +#if 0 case EL_TIMEGATE_SWITCH: ActivateTimegateSwitch(x, y); PlaySoundLevel(x, y, SND_TIMEGATE_SWITCH_ACTIVATING); return MF_ACTION; break; +#endif +#if 0 case EL_BALLOON_SWITCH_LEFT: case EL_BALLOON_SWITCH_RIGHT: case EL_BALLOON_SWITCH_UP: @@ -7498,6 +7587,7 @@ int DigField(struct PlayerInfo *player, return MF_ACTION; break; +#endif case EL_SP_PORT_LEFT: case EL_SP_PORT_RIGHT: @@ -7538,7 +7628,7 @@ int DigField(struct PlayerInfo *player, element == EL_SP_GRAVITY_PORT_RIGHT || element == EL_SP_GRAVITY_PORT_UP || element == EL_SP_GRAVITY_PORT_DOWN) - level.gravity = !level.gravity; + game.gravity = !game.gravity; /* automatically move to the next field with double speed */ player->programmed_action = move_direction; @@ -7590,6 +7680,7 @@ int DigField(struct PlayerInfo *player, } break; +#if 0 case EL_LAMP: Feld[x][y] = EL_LAMP_ACTIVE; local_player->lights_still_needed--; @@ -7597,7 +7688,9 @@ int DigField(struct PlayerInfo *player, PlaySoundLevel(x, y, SND_LAMP_ACTIVATING); return MF_ACTION; break; +#endif +#if 0 case EL_TIME_ORB_FULL: Feld[x][y] = EL_TIME_ORB_EMPTY; TimeLeft += 10; @@ -7606,6 +7699,7 @@ int DigField(struct PlayerInfo *player, PlaySoundStereo(SND_TIME_ORB_FULL_COLLECTING, SOUND_MIDDLE); return MF_ACTION; break; +#endif default: @@ -7623,7 +7717,9 @@ int DigField(struct PlayerInfo *player, if (!player->key[element - EL_GATE_1_GRAY]) return MF_NO_ACTION; } - else if (element == EL_EXIT_OPEN || element == EL_SP_EXIT_OPEN) + else if (element == EL_EXIT_OPEN || + element == EL_SP_EXIT_OPEN || + element == EL_SP_EXIT_OPENING) { sound_action = ACTION_PASSING; /* player is passing exit */ } @@ -7645,6 +7741,11 @@ int DigField(struct PlayerInfo *player, if (!IN_LEV_FIELD(nextx, nexty) || !IS_FREE(nextx, nexty)) return MF_NO_ACTION; +#if 1 + if (CAN_MOVE(element)) /* only fixed elements can be passed! */ + return MF_NO_ACTION; +#endif + if (element >= EL_EM_GATE_1 && element <= EL_EM_GATE_4) { if (!player->key[element - EL_EM_GATE_1]) @@ -7797,13 +7898,6 @@ int DigField(struct PlayerInfo *player, return MF_NO_ACTION; #if 1 - /* - printf("::: %d [%d,%d,%d => %d]\n", MovDir[x][y], - CAN_MOVE(element), move_direction, getElementMoveStepsize(x, y), - (CAN_MOVE(element) && MovDir[x][y] == move_direction && - getElementMoveStepsize(x, y) > MOVE_STEPSIZE_NORMAL) ); - */ - /* do not push elements already moving away faster than player */ if (CAN_MOVE(element) && MovDir[x][y] == move_direction && ABS(getElementMoveStepsize(x, y)) > MOVE_STEPSIZE_NORMAL) @@ -7896,17 +7990,175 @@ int DigField(struct PlayerInfo *player, break; } + else if (IS_SWITCHABLE(element)) + { + if (PLAYER_SWITCHING(player, x, y)) + return MF_ACTION; + +#if 1 + PlaySoundLevelElementAction(x, y, element, ACTION_ACTIVATING); +#endif + + if (element == EL_ROBOT_WHEEL) + { + Feld[x][y] = EL_ROBOT_WHEEL_ACTIVE; + ZX = x; + ZY = y; + + DrawLevelField(x, y); + +#if 0 + PlaySoundLevel(x, y, SND_ROBOT_WHEEL_ACTIVATING); +#endif + } + else if (element == EL_SP_TERMINAL) + { + int xx, yy; + +#if 0 + PlaySoundLevel(x, y, SND_SP_TERMINAL_ACTIVATING); +#endif + + for (yy=0; yySwitching = TRUE; + player->switch_x = x; + player->switch_y = y; + + ToggleBeltSwitch(x, y); + +#if 0 + PlaySoundLevel(x, y, SND_CLASS_CONVEYOR_BELT_SWITCH_ACTIVATING); +#endif + } + } + else if (element == EL_SWITCHGATE_SWITCH_UP || + element == EL_SWITCHGATE_SWITCH_DOWN) + { +#if 0 + if (!PLAYER_SWITCHING(player, x, y)) +#endif + { + player->Switching = TRUE; + player->switch_x = x; + player->switch_y = y; + + ToggleSwitchgateSwitch(x, y); + +#if 0 + PlaySoundLevel(x, y, SND_CLASS_SWITCHGATE_SWITCH_ACTIVATING); +#endif + } + } + else if (element == EL_LIGHT_SWITCH || + element == EL_LIGHT_SWITCH_ACTIVE) + { +#if 0 + if (!PLAYER_SWITCHING(player, x, y)) +#endif + { + player->Switching = TRUE; + player->switch_x = x; + player->switch_y = y; + + ToggleLightSwitch(x, y); + +#if 0 + PlaySoundLevel(x, y, element == EL_LIGHT_SWITCH ? + SND_LIGHT_SWITCH_ACTIVATING : + SND_LIGHT_SWITCH_DEACTIVATING); +#endif + } + } + else if (element == EL_TIMEGATE_SWITCH) + { + ActivateTimegateSwitch(x, y); + +#if 0 + PlaySoundLevel(x, y, SND_TIMEGATE_SWITCH_ACTIVATING); +#endif + } + else if (element == EL_BALLOON_SWITCH_LEFT || + element == EL_BALLOON_SWITCH_RIGHT || + element == EL_BALLOON_SWITCH_UP || + element == EL_BALLOON_SWITCH_DOWN || + element == EL_BALLOON_SWITCH_ANY) + { + if (element == EL_BALLOON_SWITCH_ANY) + game.balloon_dir = move_direction; + else + game.balloon_dir = (element == EL_BALLOON_SWITCH_LEFT ? MV_LEFT : + element == EL_BALLOON_SWITCH_RIGHT ? MV_RIGHT : + element == EL_BALLOON_SWITCH_UP ? MV_UP : + element == EL_BALLOON_SWITCH_DOWN ? MV_DOWN : + MV_NO_MOVING); + +#if 0 + PlaySoundLevel(x, y, SND_CLASS_BALLOON_SWITCH_ACTIVATING); +#endif + } + else if (element == EL_LAMP) + { + Feld[x][y] = EL_LAMP_ACTIVE; + local_player->lights_still_needed--; + + DrawLevelField(x, y); + +#if 0 + PlaySoundLevel(x, y, SND_LAMP_ACTIVATING); +#endif + } + else if (element == EL_TIME_ORB_FULL) + { + Feld[x][y] = EL_TIME_ORB_EMPTY; + TimeLeft += 10; + DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_TEXT_2); + + DrawLevelField(x, y); + +#if 0 + PlaySoundStereo(SND_TIME_ORB_FULL_COLLECTING, SOUND_MIDDLE); +#endif + } + + return MF_ACTION; + } else { #if 1 + if (!PLAYER_SWITCHING(player, x, y)) +#else + if (!player->Switching) +#endif + { + player->Switching = TRUE; + player->switch_x = x; + player->switch_y = y; + + CheckTriggeredElementSideChange(x, y, element, dig_side, + CE_OTHER_IS_SWITCHING); + CheckElementSideChange(x, y, element, dig_side, CE_SWITCHED, -1); + } + CheckTriggeredElementSideChange(x, y, element, dig_side, - CE_OTHER_GETS_PRESSED); + CE_OTHER_GETS_PRESSED); CheckElementSideChange(x, y, element, dig_side, CE_PRESSED_BY_PLAYER, -1); -#else - CheckTriggeredElementChange(x, y, element, CE_OTHER_GETS_PRESSED); - CheckElementChange(x, y, element, CE_PRESSED_BY_PLAYER); -#endif } return MF_NO_ACTION;