X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fgame.c;h=bac83725cb81b334bd9511d71ef56a865744b23d;hp=bf9b3892aa42200833396a0e620a41f2b41b3425;hb=4b1b5a2a67227d3023ff6da4596be31eae8eaefc;hpb=940ec320c7cdae17cda81436408c2f75b8c9a524 diff --git a/src/game.c b/src/game.c index bf9b3892..bac83725 100644 --- a/src/game.c +++ b/src/game.c @@ -28,16 +28,20 @@ #define USE_NEW_AMOEBA_CODE FALSE /* EXPERIMENTAL STUFF */ -#define USE_NEW_STUFF TRUE * 1 +#define USE_NEW_STUFF (TRUE * 1) -#define USE_NEW_MOVE_STYLE TRUE * USE_NEW_STUFF * 1 -#define USE_NEW_MOVE_DELAY TRUE * USE_NEW_STUFF * 1 -#define USE_NEW_PUSH_DELAY TRUE * USE_NEW_STUFF * 1 -#define USE_NEW_BLOCK_STYLE TRUE * USE_NEW_STUFF * 1 * 1 -#define USE_NEW_SP_SLIPPERY TRUE * USE_NEW_STUFF * 1 -#define USE_NEW_RANDOMIZE TRUE * USE_NEW_STUFF * 1 +#define USE_NEW_MOVE_STYLE (TRUE * USE_NEW_STUFF * 1) +#define USE_NEW_MOVE_DELAY (TRUE * USE_NEW_STUFF * 1) +#define USE_NEW_PUSH_DELAY (TRUE * USE_NEW_STUFF * 1) +#define USE_NEW_BLOCK_STYLE (TRUE * USE_NEW_STUFF * 1) +#define USE_NEW_SP_SLIPPERY (TRUE * USE_NEW_STUFF * 1) +#define USE_NEW_RANDOMIZE (TRUE * USE_NEW_STUFF * 1) + +#define USE_PUSH_BUGFIX (TRUE * USE_NEW_STUFF * 1) + +#define USE_CAN_MOVE_NOT_MOVING (TRUE * USE_NEW_STUFF * 1) +#define USE_PREVIOUS_MOVE_DIR (TRUE * USE_NEW_STUFF * 1) -#define USE_PUSH_BUGFIX TRUE * 1 /* for DigField() */ #define DF_NO_PUSH 0 @@ -1062,12 +1066,13 @@ inline void DrawGameValue_Dynamite(int value) DrawText(DX_DYNAMITE, DY_DYNAMITE, int2str(value, 3), FONT_TEXT_2); } -inline void DrawGameValue_Keys(struct PlayerInfo *player) +inline void DrawGameValue_Keys(int key[MAX_NUM_KEYS]) { int i; - for (i = 0; i < MAX_KEYS; i++) - if (player->key[i]) + /* currently only 4 of 8 possible keys are displayed */ + for (i = 0; i < STD_NUM_KEYS; i++) + if (key[i]) DrawMiniGraphicExt(drawto, DX_KEYS + i * MINI_TILEX, DY_KEYS, el2edimg(EL_KEY_1 + i)); } @@ -1109,19 +1114,45 @@ inline void DrawGameValue_Level(int value) } } -void DrawGameDoorValues() +void DrawAllGameValues(int emeralds, int dynamite, int score, int time, + int key_bits) { + int key[MAX_NUM_KEYS]; int i; + for (i = 0; i < MAX_NUM_KEYS; i++) + key[i] = key_bits & (1 << i); + DrawGameValue_Level(level_nr); - for (i = 0; i < MAX_PLAYERS; i++) - DrawGameValue_Keys(&stored_player[i]); + DrawGameValue_Emeralds(emeralds); + DrawGameValue_Dynamite(dynamite); + DrawGameValue_Score(score); + DrawGameValue_Time(time); + + DrawGameValue_Keys(key); +} + +void DrawGameDoorValues() +{ + int i; + + if (level.game_engine_type == GAME_ENGINE_TYPE_EM) + { + DrawGameDoorValues_EM(); + + return; + } + + DrawGameValue_Level(level_nr); DrawGameValue_Emeralds(local_player->gems_still_needed); DrawGameValue_Dynamite(local_player->inventory_size); DrawGameValue_Score(local_player->score); DrawGameValue_Time(TimeLeft); + + for (i = 0; i < MAX_PLAYERS; i++) + DrawGameValue_Keys(stored_player[i].key); } static void resolve_group_element(int group_element, int recursion_depth) @@ -1560,7 +1591,7 @@ void InitGame() player->lights_still_needed = 0; player->friends_still_needed = 0; - for (j = 0; j < MAX_KEYS; j++) + for (j = 0; j < MAX_NUM_KEYS; j++) player->key[j] = FALSE; player->dynabomb_count = 0; @@ -1691,6 +1722,7 @@ void InitGame() #endif ZX = ZY = -1; + ExitX = ExitY = -1; FrameCounter = 0; TimeFrames = 0; @@ -2052,18 +2084,27 @@ void InitGame() CloseDoor(DOOR_CLOSE_1); - DrawLevel(); - DrawAllPlayers(); + /* !!! FIX THIS (START) !!! */ + if (level.game_engine_type == GAME_ENGINE_TYPE_EM) + { + InitGameEngine_EM(); + } + else + { + DrawLevel(); + DrawAllPlayers(); - /* after drawing the level, correct some elements */ - if (game.timegate_time_left == 0) - CloseAllOpenTimegates(); + /* after drawing the level, correct some elements */ + if (game.timegate_time_left == 0) + CloseAllOpenTimegates(); - if (setup.soft_scrolling) - BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY); + if (setup.soft_scrolling) + BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY); - redraw_mask |= REDRAW_FROM_BACKBUFFER; - FadeToFront(); + redraw_mask |= REDRAW_FROM_BACKBUFFER; + FadeToFront(); + } + /* !!! FIX THIS (END) !!! */ /* copy default game door content to main double buffer */ BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, @@ -2104,6 +2145,15 @@ void InitGame() #endif } +void UpdateEngineValues(int actual_scroll_x, int actual_scroll_y) +{ + /* this is used for non-R'n'D game engines to update certain engine values */ + + /* needed to determine if sounds are played within the visible screen area */ + scroll_x = actual_scroll_x; + scroll_y = actual_scroll_y; +} + void InitMovDir(int x, int y) { int i, element = Feld[x][y]; @@ -2374,8 +2424,9 @@ void GameWon() } /* close exit door after last player */ - if ((Feld[ExitX][ExitY] == EL_EXIT_OPEN || - Feld[ExitX][ExitY] == EL_SP_EXIT_OPEN) && AllPlayersGone) + if (AllPlayersGone && ExitX >= 0 && ExitY >= 0 && + (Feld[ExitX][ExitY] == EL_EXIT_OPEN || + Feld[ExitX][ExitY] == EL_SP_EXIT_OPEN)) { int element = Feld[ExitX][ExitY]; @@ -2386,7 +2437,9 @@ void GameWon() } /* Hero disappears */ - DrawLevelField(ExitX, ExitY); + if (ExitX >= 0 && ExitY >= 0) + DrawLevelField(ExitX, ExitY); + BackToFront(); if (tape.playing) @@ -2495,6 +2548,37 @@ int NewHiScore() return position; } +inline static int getElementMoveStepsize(int x, int y) +{ + int element = Feld[x][y]; + int direction = MovDir[x][y]; + int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0); + int dy = (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0); + int horiz_move = (dx != 0); + int sign = (horiz_move ? dx : dy); + int step = sign * element_info[element].move_stepsize; + + /* special values for move stepsize for spring and things on conveyor belt */ + if (horiz_move) + { +#if 0 + if (element == EL_SPRING) + step = sign * MOVE_STEPSIZE_NORMAL * 2; + else if (CAN_FALL(element) && !CAN_MOVE(element) && + y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1])) + step = sign * MOVE_STEPSIZE_NORMAL / 2; +#else + 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; +#endif + } + + return step; +} + void InitPlayerGfxAnimation(struct PlayerInfo *player, int action, int dir) { if (player->GfxAction != action || player->GfxDir != dir) @@ -2534,6 +2618,27 @@ void InitMovingField(int x, int y, int direction) if (!WasJustMoving[x][y] || direction != MovDir[x][y]) ResetGfxAnimation(x, y); +#if USE_CAN_MOVE_NOT_MOVING + + MovDir[x][y] = direction; + GfxDir[x][y] = direction; + GfxAction[x][y] = (direction == MV_DOWN && CAN_FALL(element) ? + ACTION_FALLING : ACTION_MOVING); + + if (getElementMoveStepsize(x, y) != 0) /* moving or being moved */ + { + if (Feld[newx][newy] == EL_EMPTY) + Feld[newx][newy] = EL_BLOCKED; + + MovDir[newx][newy] = MovDir[x][y]; + GfxFrame[newx][newy] = GfxFrame[x][y]; + GfxRandom[newx][newy] = GfxRandom[x][y]; + GfxAction[newx][newy] = GfxAction[x][y]; + GfxDir[newx][newy] = GfxDir[x][y]; + } + +#else + MovDir[newx][newy] = MovDir[x][y] = direction; GfxDir[x][y] = direction; @@ -2549,6 +2654,7 @@ void InitMovingField(int x, int y, int direction) GfxRandom[newx][newy] = GfxRandom[x][y]; GfxAction[newx][newy] = GfxAction[x][y]; GfxDir[newx][newy] = GfxDir[x][y]; +#endif } void Moving2Blocked(int x, int y, int *goes_to_x, int *goes_to_y) @@ -3108,8 +3214,15 @@ void Explode(int ex, int ey, int phase, int mode) return; #endif +#if 1 + if (mode == EX_TYPE_NORMAL || + mode == EX_TYPE_CENTER || + mode == EX_TYPE_CROSS) + PlayLevelSoundAction(ex, ey, ACTION_EXPLODING); +#else if (mode == EX_TYPE_NORMAL || mode == EX_TYPE_CENTER) PlayLevelSoundAction(ex, ey, ACTION_EXPLODING); +#endif /* remove things displayed in background while burning dynamite */ if (Back[ex][ey] != EL_EMPTY && !IS_INDESTRUCTIBLE(Back[ex][ey])) @@ -4115,6 +4228,10 @@ static void RedrawAllLightSwitchesAndInvisibleElements() Feld[x][y] = getInvisibleActiveFromInvisibleElement(element); DrawLevelField(x, y); + + /* uncrumble neighbour fields, if needed */ + if (element == EL_INVISIBLE_SAND) + DrawLevelFieldCrumbledSandNeighbours(x, y); } else if (element == EL_INVISIBLE_STEELWALL_ACTIVE || element == EL_INVISIBLE_WALL_ACTIVE || @@ -4124,6 +4241,10 @@ static void RedrawAllLightSwitchesAndInvisibleElements() Feld[x][y] = getInvisibleFromInvisibleActiveElement(element); DrawLevelField(x, y); + + /* re-crumble neighbour fields, if needed */ + if (element == EL_INVISIBLE_SAND) + DrawLevelFieldCrumbledSandNeighbours(x, y); } } } @@ -4173,37 +4294,6 @@ static void ActivateTimegateSwitch(int x, int y) Feld[x][y] = EL_TIMEGATE_SWITCH_ACTIVE; } -inline static int getElementMoveStepsize(int x, int y) -{ - int element = Feld[x][y]; - int direction = MovDir[x][y]; - int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0); - int dy = (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0); - int horiz_move = (dx != 0); - int sign = (horiz_move ? dx : dy); - int step = sign * element_info[element].move_stepsize; - - /* special values for move stepsize for spring and things on conveyor belt */ - if (horiz_move) - { -#if 0 - if (element == EL_SPRING) - step = sign * MOVE_STEPSIZE_NORMAL * 2; - else if (CAN_FALL(element) && !CAN_MOVE(element) && - y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1])) - step = sign * MOVE_STEPSIZE_NORMAL / 2; -#else - 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; -#endif - } - - return step; -} - void Impact(int x, int y) { boolean lastline = (y == lev_fieldy-1); @@ -4942,6 +5032,11 @@ inline static void TurnRoundExt(int x, int y) boolean can_turn_right = CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, right_x,right_y); +#if USE_CAN_MOVE_NOT_MOVING + if (element_info[element].move_stepsize == 0) /* not moving */ + return; +#endif + if (move_pattern == MV_TURNING_LEFT) MovDir[x][y] = left_dir; else if (move_pattern == MV_TURNING_RIGHT) @@ -5052,6 +5147,16 @@ inline static void TurnRoundExt(int x, int y) boolean first_horiz = RND(2); int new_move_dir = MovDir[x][y]; +#if USE_CAN_MOVE_NOT_MOVING + if (element_info[element].move_stepsize == 0) /* not moving */ + { + first_horiz = (ABS(attr_x - x) >= ABS(attr_y - y)); + MovDir[x][y] &= (first_horiz ? MV_HORIZONTAL : MV_VERTICAL); + + return; + } +#endif + MovDir[x][y] = new_move_dir & (first_horiz ? MV_HORIZONTAL : MV_VERTICAL); Moving2Blocked(x, y, &newx, &newy); @@ -5145,7 +5250,13 @@ inline static void TurnRoundExt(int x, int y) MovDir[x][y] = new_move_dir; if (old_move_dir != new_move_dir) + { +#if 1 + MovDelay[x][y] = GET_NEW_MOVE_DELAY(element); +#else MovDelay[x][y] = 9; +#endif + } } } @@ -6352,7 +6463,9 @@ void ContinueMoving(int x, int y) #endif Store[x][y] = EL_EMPTY; - MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0; + MovPos[x][y] = 0; + MovDir[x][y] = 0; + MovDelay[x][y] = 0; MovDelay[newx][newy] = 0; if (CAN_CHANGE(element)) @@ -6377,7 +6490,10 @@ void ContinueMoving(int x, int y) Pushed[x][y] = Pushed[newx][newy] = FALSE; +#if 0 + /* do this after checking for left-behind element */ ResetGfxAnimation(x, y); /* reset animation values for old field */ +#endif #if 1 /* some elements can leave other elements behind after moving */ @@ -6394,6 +6510,12 @@ void ContinueMoving(int x, int y) int move_leave_element = ei->move_leave_element; Feld[x][y] = move_leave_element; + +#if USE_PREVIOUS_MOVE_DIR + if (element_info[Feld[x][y]].move_direction_initial == MV_START_PREVIOUS) + MovDir[x][y] = direction; +#endif + InitField(x, y, FALSE); if (GFX_CRUMBLED(Feld[x][y])) @@ -6422,6 +6544,11 @@ void ContinueMoving(int x, int y) ei->can_leave_element = FALSE; #endif +#if 1 + /* do this after checking for left-behind element */ + ResetGfxAnimation(x, y); /* reset animation values for old field */ +#endif + #if 0 /* 2.1.1 (does not work correctly for spring) */ if (!CAN_MOVE(element)) @@ -8506,8 +8633,8 @@ void AdvanceFrameAndPlayerCounters(int player_nr) void GameActions() { - static unsigned long action_delay = 0; - unsigned long action_delay_value; + static unsigned long game_frame_delay = 0; + unsigned long game_frame_delay_value; int magic_wall_x = 0, magic_wall_y = 0; int i, x, y, element, graphic; byte *recorded_player_action; @@ -8519,15 +8646,15 @@ void GameActions() if (game_status != GAME_MODE_PLAYING) return; - action_delay_value = + game_frame_delay_value = (tape.playing && tape.fast_forward ? FfwdFrameDelay : GameFrameDelay); if (tape.playing && tape.warp_forward && !tape.pausing) - action_delay_value = 0; + game_frame_delay_value = 0; /* ---------- main game synchronization point ---------- */ - WaitUntilDelayReached(&action_delay, action_delay_value); + WaitUntilDelayReached(&game_frame_delay, game_frame_delay_value); if (network_playing && !network_player_action_received) { @@ -8566,6 +8693,7 @@ void GameActions() recorded_player_action = (tape.playing ? TapePlayAction() : NULL); #if 1 + /* !!! CHECK THIS (tape.pausing is always FALSE here!) !!! */ if (recorded_player_action == NULL && tape.pausing) return; #endif @@ -9356,6 +9484,9 @@ static boolean canFallDown(struct PlayerInfo *player) return (IN_LEV_FIELD(jx, jy + 1) && (IS_FREE(jx, jy + 1) || +#if USE_NEW_BLOCK_STYLE + Feld[jx][jy + 1] == EL_PLAYER_IS_LEAVING || +#endif (Feld[jx][jy + 1] == EL_ACID && player->can_fall_into_acid)) && IS_WALKABLE_FROM(Feld[jx][jy], MV_DOWN) && !IS_WALKABLE_INSIDE(Feld[jx][jy])); @@ -9634,7 +9765,7 @@ boolean MovePlayerOneStep(struct PlayerInfo *player, /* check if DigField() has caused relocation of the player */ if (player->jx != jx || player->jy != jy) - return MF_NO_ACTION; + return MF_NO_ACTION; /* <-- !!! CHECK THIS [-> MF_ACTION ?] !!! */ StorePlayer[jx][jy] = 0; player->last_jx = jx; @@ -11298,14 +11429,14 @@ int DigField(struct PlayerInfo *player, return MF_NO_ACTION; /* player cannot walk here due to gravity */ #endif - if (IS_GATE(element)) + if (IS_RND_GATE(element)) { - if (!player->key[element - EL_GATE_1]) + if (!player->key[RND_GATE_NR(element)]) return MF_NO_ACTION; } - else if (IS_GATE_GRAY(element)) + else if (IS_RND_GATE_GRAY(element)) { - if (!player->key[element - EL_GATE_1_GRAY]) + if (!player->key[RND_GATE_GRAY_NR(element)]) return MF_NO_ACTION; } else if (element == EL_EXIT_OPEN || @@ -11368,12 +11499,12 @@ int DigField(struct PlayerInfo *player, if (IS_EM_GATE(element)) { - if (!player->key[element - EL_EM_GATE_1]) + if (!player->key[EM_GATE_NR(element)]) return MF_NO_ACTION; } else if (IS_EM_GATE_GRAY(element)) { - if (!player->key[element - EL_EM_GATE_1_GRAY]) + if (!player->key[EM_GATE_GRAY_NR(element)]) return MF_NO_ACTION; } else if (IS_SP_PORT(element)) @@ -11484,15 +11615,11 @@ int DigField(struct PlayerInfo *player, { player->dynabomb_xl = TRUE; } - else if ((element >= EL_KEY_1 && element <= EL_KEY_4) || - (element >= EL_EM_KEY_1 && element <= EL_EM_KEY_4)) + else if (IS_KEY(element)) { - 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; + player->key[KEY_NR(element)] = TRUE; - DrawGameValue_Keys(player); + DrawGameValue_Keys(player->key); redraw_mask |= REDRAW_DOOR_1; } @@ -12370,6 +12497,168 @@ static void PlayLevelMusic() PlayMusic(MAP_NOCONF_MUSIC(level_nr)); /* from music dir */ } +void PlayLevelSound_EM(int x, int y, int element_em, int sample) +{ + int element = (element_em > -1 ? map_element_EM_to_RND(element_em) : 0); + +#if 0 + if (sample == SAMPLE_bug) + printf("::: PlayLevelSound_EM: %d, %d: %d\n", x, y, sample); +#endif + + switch (sample) + { + case SAMPLE_blank: + PlayLevelSoundElementAction(x, y, element, ACTION_WALKING); + break; + + case SAMPLE_roll: + PlayLevelSoundElementAction(x, y, element, ACTION_PUSHING); + break; + + case SAMPLE_stone: + PlayLevelSoundElementAction(x, y, element, ACTION_IMPACT); + break; + + case SAMPLE_nut: + PlayLevelSoundElementAction(x, y, element, ACTION_IMPACT); + break; + + case SAMPLE_crack: + PlayLevelSoundElementAction(x, y, element, ACTION_BREAKING); + break; + + case SAMPLE_bug: + PlayLevelSoundElementAction(x, y, element, ACTION_MOVING); + break; + + case SAMPLE_tank: + PlayLevelSoundElementAction(x, y, element, ACTION_MOVING); + break; + + case SAMPLE_android_clone: + PlayLevelSoundElementAction(x, y, element, ACTION_DROPPING); + break; + + case SAMPLE_android_move: + PlayLevelSoundElementAction(x, y, element, ACTION_MOVING); + break; + + case SAMPLE_spring: + PlayLevelSoundElementAction(x, y, element, ACTION_IMPACT); + break; + + case SAMPLE_slurp: + PlayLevelSoundElementAction(x, y, element, ACTION_SLURPED_BY_SPRING); + break; + + case SAMPLE_eater: + PlayLevelSoundElementAction(x, y, element, ACTION_WAITING); + break; + + case SAMPLE_eater_eat: + PlayLevelSoundElementAction(x, y, element, ACTION_DIGGING); + break; + + case SAMPLE_alien: + PlayLevelSoundElementAction(x, y, element, ACTION_MOVING); + break; + + case SAMPLE_collect: + PlayLevelSoundElementAction(x, y, element, ACTION_COLLECTING); + break; + + case SAMPLE_diamond: + PlayLevelSoundElementAction(x, y, element, ACTION_IMPACT); + break; + + case SAMPLE_squash: + /* !!! CHECK THIS !!! */ +#if 1 + PlayLevelSoundElementAction(x, y, element, ACTION_BREAKING); +#else + PlayLevelSoundElementAction(x, y, element, ACTION_SMASHED_BY_ROCK); +#endif + break; + + case SAMPLE_wonderfall: + PlayLevelSoundElementAction(x, y, element, ACTION_FILLING); + break; + + case SAMPLE_drip: + PlayLevelSoundElementAction(x, y, element, ACTION_IMPACT); + break; + + case SAMPLE_push: + PlayLevelSoundElementAction(x, y, element, ACTION_PUSHING); + break; + + case SAMPLE_dirt: + PlayLevelSoundElementAction(x, y, element, ACTION_DIGGING); + break; + + case SAMPLE_acid: + PlayLevelSoundElementAction(x, y, element, ACTION_SPLASHING); + break; + + case SAMPLE_ball: + PlayLevelSoundElementAction(x, y, element, ACTION_DROPPING); + break; + + case SAMPLE_grow: + PlayLevelSoundElementAction(x, y, element, ACTION_GROWING); + break; + + case SAMPLE_wonder: + PlayLevelSoundElementAction(x, y, element, ACTION_ACTIVE); + break; + + case SAMPLE_door: + PlayLevelSoundElementAction(x, y, element, ACTION_PASSING); + break; + + case SAMPLE_exit_open: + PlayLevelSoundElementAction(x, y, element, ACTION_OPENING); + break; + + case SAMPLE_exit_leave: + PlayLevelSoundElementAction(x, y, element, ACTION_PASSING); + break; + + case SAMPLE_dynamite: + PlayLevelSoundElementAction(x, y, element, ACTION_DROPPING); + break; + + case SAMPLE_tick: + PlayLevelSoundElementAction(x, y, element, ACTION_ACTIVE); + break; + + case SAMPLE_press: + PlayLevelSoundElementAction(x, y, element, ACTION_ACTIVATING); + break; + + case SAMPLE_wheel: + PlayLevelSoundElementAction(x, y, element, ACTION_ACTIVE); + break; + + case SAMPLE_boom: + PlayLevelSoundElementAction(x, y, element, ACTION_EXPLODING); + break; + + case SAMPLE_die: + PlayLevelSoundElementAction(x, y, element, ACTION_DYING); + break; + + case SAMPLE_time: + PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MIDDLE); + break; + + default: + PlayLevelSoundElementAction(x, y, element, ACTION_DEFAULT); + break; + } +} + void RaiseScore(int value) { local_player->score += value; @@ -12439,6 +12728,14 @@ void RaiseScoreElement(int element) case EL_KEY_2: case EL_KEY_3: case EL_KEY_4: + case EL_EM_KEY_1: + case EL_EM_KEY_2: + case EL_EM_KEY_3: + case EL_EM_KEY_4: + case EL_EMC_KEY_5: + case EL_EMC_KEY_6: + case EL_EMC_KEY_7: + case EL_EMC_KEY_8: RaiseScore(level.score[SC_KEY]); break; default: