X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fgame.c;h=1de51be5b909b1e0cc2b0f735fa0e7f989fc7771;hp=1bfe0100d1084c4214ad9cbaff4026f1456bf450;hb=5c6c42f1;hpb=7e68d10c8f4c814e532cc30f6fc721c269a99cb6 diff --git a/src/game.c b/src/game.c index 1bfe0100..1de51be5 100644 --- a/src/game.c +++ b/src/game.c @@ -1002,6 +1002,8 @@ static struct GamePanelControlInfo game_panel_controls[] = #define IS_PASSABLE_FROM(e, d) (IS_PASSABLE(e) && ACCESS_FROM(e, d)) #define IS_ACCESSIBLE_FROM(e, d) (IS_ACCESSIBLE(e) && ACCESS_FROM(e, d)) +#define MM_HEALTH(x) (MIN(MAX(0, MAX_HEALTH - (x)), MAX_HEALTH)) + /* game button identifiers */ #define GAME_CTRL_ID_STOP 0 #define GAME_CTRL_ID_PAUSE 1 @@ -1011,11 +1013,17 @@ static struct GamePanelControlInfo game_panel_controls[] = #define GAME_CTRL_ID_SAVE 5 #define GAME_CTRL_ID_PAUSE2 6 #define GAME_CTRL_ID_LOAD 7 -#define SOUND_CTRL_ID_MUSIC 8 -#define SOUND_CTRL_ID_LOOPS 9 -#define SOUND_CTRL_ID_SIMPLE 10 +#define GAME_CTRL_ID_PANEL_STOP 8 +#define GAME_CTRL_ID_PANEL_PAUSE 9 +#define GAME_CTRL_ID_PANEL_PLAY 10 +#define SOUND_CTRL_ID_MUSIC 11 +#define SOUND_CTRL_ID_LOOPS 12 +#define SOUND_CTRL_ID_SIMPLE 13 +#define SOUND_CTRL_ID_PANEL_MUSIC 14 +#define SOUND_CTRL_ID_PANEL_LOOPS 15 +#define SOUND_CTRL_ID_PANEL_SIMPLE 16 -#define NUM_GAME_BUTTONS 11 +#define NUM_GAME_BUTTONS 17 /* forward declaration for internal use */ @@ -2205,8 +2213,11 @@ void UpdateGameControlValues() local_player->gems_still_needed > 0 || local_player->sokobanfields_still_needed > 0 || local_player->lights_still_needed > 0); - int health = (level.game_engine_type == GAME_ENGINE_TYPE_MM ? - MIN(MAX(0, 100 - game_mm.laser_overload_value), 100) : 100); + int health = (local_player->LevelSolved ? + local_player->LevelSolved_CountingHealth : + level.game_engine_type == GAME_ENGINE_TYPE_MM ? + MM_HEALTH(game_mm.laser_overload_value) : + local_player->health); UpdatePlayfieldElementCount(); @@ -3287,7 +3298,7 @@ void InitGame() else FadeSetEnterScreen(); - if (CheckIfGlobalBorderHasChanged()) + if (CheckIfGlobalBorderOrPlayfieldViewportHasChanged()) fade_mask = REDRAW_ALL; FadeLevelSoundsAndMusic(); @@ -3334,9 +3345,16 @@ void InitGame() player->mouse_action.ly = 0; player->mouse_action.button = 0; + player->effective_mouse_action.lx = 0; + player->effective_mouse_action.ly = 0; + player->effective_mouse_action.button = 0; + player->score = 0; player->score_final = 0; + player->health = MAX_HEALTH; + player->health_final = MAX_HEALTH; + player->gems_still_needed = level.gems_needed; player->sokobanfields_still_needed = 0; player->lights_still_needed = 0; @@ -3472,8 +3490,10 @@ void InitGame() player->LevelSolved_PanelOff = FALSE; player->LevelSolved_SaveTape = FALSE; player->LevelSolved_SaveScore = FALSE; + player->LevelSolved_CountingTime = 0; player->LevelSolved_CountingScore = 0; + player->LevelSolved_CountingHealth = 0; map_player_action[i] = i; } @@ -4155,10 +4175,6 @@ void InitGame() FreeGameButtons(); CreateGameButtons(); - game_gadget[SOUND_CTRL_ID_MUSIC]->checked = setup.sound_music; - game_gadget[SOUND_CTRL_ID_LOOPS]->checked = setup.sound_loops; - game_gadget[SOUND_CTRL_ID_SIMPLE]->checked = setup.sound_simple; - MapGameButtons(); MapTapeButtons(); @@ -4446,20 +4462,28 @@ static void PlayerWins(struct PlayerInfo *player) level.game_engine_type == GAME_ENGINE_TYPE_MM ? game_mm.score : player->score); + player->health_final = (level.game_engine_type == GAME_ENGINE_TYPE_MM ? + MM_HEALTH(game_mm.laser_overload_value) : + player->health); player->LevelSolved_CountingTime = (game.no_time_limit ? TimePlayed : TimeLeft); player->LevelSolved_CountingScore = player->score_final; + player->LevelSolved_CountingHealth = player->health_final; } void GameWon() { + static int time_count_steps; static int time, time_final; static int score, score_final; + static int health, health_final; static int game_over_delay_1 = 0; static int game_over_delay_2 = 0; + static int game_over_delay_3 = 0; int game_over_delay_value_1 = 50; - int game_over_delay_value_2 = 50; + int game_over_delay_value_2 = 25; + int game_over_delay_value_3 = 50; if (!local_player->LevelSolved_GameWon) { @@ -4485,24 +4509,42 @@ void GameWon() TapeStop(); - game_over_delay_1 = game_over_delay_value_1; - game_over_delay_2 = game_over_delay_value_2; + game_over_delay_1 = 0; + game_over_delay_2 = 0; + game_over_delay_3 = game_over_delay_value_3; time = time_final = (game.no_time_limit ? TimePlayed : TimeLeft); score = score_final = local_player->score_final; + health = health_final = local_player->health_final; - if (TimeLeft > 0) + if (level.score[SC_TIME_BONUS] > 0) { - time_final = 0; - score_final += TimeLeft * level.score[SC_TIME_BONUS]; - } - else if (game.no_time_limit && TimePlayed < 999) - { - time_final = 999; - score_final += (999 - TimePlayed) * level.score[SC_TIME_BONUS]; - } + if (TimeLeft > 0) + { + time_final = 0; + score_final += TimeLeft * level.score[SC_TIME_BONUS]; + } + else if (game.no_time_limit && TimePlayed < 999) + { + time_final = 999; + score_final += (999 - TimePlayed) * level.score[SC_TIME_BONUS]; + } + + time_count_steps = MAX(1, ABS(time_final - time) / 100); + + game_over_delay_1 = game_over_delay_value_1; + + if (level.game_engine_type == GAME_ENGINE_TYPE_MM) + { + health_final = 0; + score_final += health * level.score[SC_TIME_BONUS]; + + game_over_delay_2 = game_over_delay_value_2; + } - local_player->score_final = score_final; + local_player->score_final = score_final; + local_player->health_final = health_final; + } if (level_editor_test_game) { @@ -4574,7 +4616,9 @@ void GameWon() { int time_to_go = ABS(time_final - time); int time_count_dir = (time < time_final ? +1 : -1); - int time_count_steps = (time_to_go > 100 && time_to_go % 10 == 0 ? 10 : 1); + + if (time_to_go < time_count_steps) + time_count_steps = 1; time += time_count_steps * time_count_dir; score += time_count_steps * level.score[SC_TIME_BONUS]; @@ -4597,8 +4641,6 @@ void GameWon() return; } - local_player->LevelSolved_PanelOff = TRUE; - if (game_over_delay_2 > 0) { game_over_delay_2--; @@ -4606,6 +4648,40 @@ void GameWon() return; } + if (health != health_final) + { + int health_count_dir = (health < health_final ? +1 : -1); + + health += health_count_dir; + score += level.score[SC_TIME_BONUS]; + + local_player->LevelSolved_CountingHealth = health; + local_player->LevelSolved_CountingScore = score; + + game_panel_controls[GAME_PANEL_HEALTH].value = health; + game_panel_controls[GAME_PANEL_SCORE].value = score; + + DisplayGameControlValues(); + + if (health == health_final) + StopSound(SND_GAME_LEVELTIME_BONUS); + else if (setup.sound_loops) + PlaySoundLoop(SND_GAME_LEVELTIME_BONUS); + else + PlaySound(SND_GAME_LEVELTIME_BONUS); + + return; + } + + local_player->LevelSolved_PanelOff = TRUE; + + if (game_over_delay_3 > 0) + { + game_over_delay_3--; + + return; + } + GameEnd(); } @@ -10974,6 +11050,28 @@ static byte PlayerActions(struct PlayerInfo *player, byte player_action) } } +static void SetMouseActionFromTapeAction(struct MouseActionInfo *mouse_action, + byte *tape_action) +{ + if (!tape.use_mouse) + return; + + mouse_action->lx = tape_action[TAPE_ACTION_LX]; + mouse_action->ly = tape_action[TAPE_ACTION_LY]; + mouse_action->button = tape_action[TAPE_ACTION_BUTTON]; +} + +static void SetTapeActionFromMouseAction(byte *tape_action, + struct MouseActionInfo *mouse_action) +{ + if (!tape.use_mouse) + return; + + tape_action[TAPE_ACTION_LX] = mouse_action->lx; + tape_action[TAPE_ACTION_LY] = mouse_action->ly; + tape_action[TAPE_ACTION_BUTTON] = mouse_action->button; +} + static void CheckLevelTime() { int i; @@ -11301,6 +11399,12 @@ void GameActionsExt() /* when playing tape, read previously recorded player input from tape data */ recorded_player_action = (tape.playing ? TapePlayAction() : NULL); + local_player->effective_mouse_action = local_player->mouse_action; + + if (recorded_player_action != NULL) + SetMouseActionFromTapeAction(&local_player->effective_mouse_action, + recorded_player_action); + /* TapePlayAction() may return NULL when toggling to "pause before death" */ if (tape.pausing) return; @@ -11357,6 +11461,9 @@ void GameActionsExt() tape.player_participates[i] = TRUE; } + SetTapeActionFromMouseAction(tape_action, + &local_player->effective_mouse_action); + /* only record actions from input devices, but not programmed actions */ if (tape.recording) TapeRecordAction(tape_action); @@ -11515,7 +11622,7 @@ void GameActions_MM_Main() { boolean warp_mode = (tape.playing && tape.warp_forward && !tape.pausing); - GameActions_MM(local_player->mouse_action, warp_mode); + GameActions_MM(local_player->effective_mouse_action, warp_mode); } void GameActions_RND_Main() @@ -14673,6 +14780,50 @@ void PlayLevelSound_SP(int xx, int yy, int element_sp, int action_sp) PlayLevelSoundElementAction(x, y, element, action); } +void PlayLevelSound_MM(int xx, int yy, int element_mm, int action_mm) +{ + int element = map_element_MM_to_RND(element_mm); + int action = map_action_MM_to_RND(action_mm); + int offset = 0; + int x = xx - offset; + int y = yy - offset; + + if (!IS_MM_ELEMENT(element)) + element = EL_MM_DEFAULT; + + PlayLevelSoundElementAction(x, y, element, action); +} + +void PlaySound_MM(int sound_mm) +{ + int sound = map_sound_MM_to_RND(sound_mm); + + if (sound == SND_UNDEFINED) + return; + + PlaySound(sound); +} + +void PlaySoundLoop_MM(int sound_mm) +{ + int sound = map_sound_MM_to_RND(sound_mm); + + if (sound == SND_UNDEFINED) + return; + + PlaySoundLoop(sound); +} + +void StopSound_MM(int sound_mm) +{ + int sound = map_sound_MM_to_RND(sound_mm); + + if (sound == SND_UNDEFINED) + return; + + StopSound(sound); +} + void RaiseScore(int value) { local_player->score += value; @@ -15159,52 +15310,95 @@ static struct int graphic; struct XY *pos; int gadget_id; + boolean *setup_value; + boolean allowed_on_tape; char *infotext; } gamebutton_info[NUM_GAME_BUTTONS] = { { - IMG_GFX_GAME_BUTTON_STOP, &game.button.stop, - GAME_CTRL_ID_STOP, "stop game" + IMG_GFX_GAME_BUTTON_STOP, &game.button.stop, + GAME_CTRL_ID_STOP, NULL, + TRUE, "stop game" + }, + { + IMG_GFX_GAME_BUTTON_PAUSE, &game.button.pause, + GAME_CTRL_ID_PAUSE, NULL, + TRUE, "pause game" + }, + { + IMG_GFX_GAME_BUTTON_PLAY, &game.button.play, + GAME_CTRL_ID_PLAY, NULL, + TRUE, "play game" + }, + { + IMG_GFX_GAME_BUTTON_UNDO, &game.button.undo, + GAME_CTRL_ID_UNDO, NULL, + TRUE, "undo step" + }, + { + IMG_GFX_GAME_BUTTON_REDO, &game.button.redo, + GAME_CTRL_ID_REDO, NULL, + TRUE, "redo step" + }, + { + IMG_GFX_GAME_BUTTON_SAVE, &game.button.save, + GAME_CTRL_ID_SAVE, NULL, + TRUE, "save game" }, { - IMG_GFX_GAME_BUTTON_PAUSE, &game.button.pause, - GAME_CTRL_ID_PAUSE, "pause game" + IMG_GFX_GAME_BUTTON_PAUSE2, &game.button.pause2, + GAME_CTRL_ID_PAUSE2, NULL, + TRUE, "pause game" }, { - IMG_GFX_GAME_BUTTON_PLAY, &game.button.play, - GAME_CTRL_ID_PLAY, "play game" + IMG_GFX_GAME_BUTTON_LOAD, &game.button.load, + GAME_CTRL_ID_LOAD, NULL, + TRUE, "load game" }, { - IMG_GFX_GAME_BUTTON_UNDO, &game.button.undo, - GAME_CTRL_ID_UNDO, "undo step" + IMG_GFX_GAME_BUTTON_PANEL_STOP, &game.button.panel_stop, + GAME_CTRL_ID_PANEL_STOP, NULL, + FALSE, "stop game" }, { - IMG_GFX_GAME_BUTTON_REDO, &game.button.redo, - GAME_CTRL_ID_REDO, "redo step" + IMG_GFX_GAME_BUTTON_PANEL_PAUSE, &game.button.panel_pause, + GAME_CTRL_ID_PANEL_PAUSE, NULL, + FALSE, "pause game" }, { - IMG_GFX_GAME_BUTTON_SAVE, &game.button.save, - GAME_CTRL_ID_SAVE, "save game" + IMG_GFX_GAME_BUTTON_PANEL_PLAY, &game.button.panel_play, + GAME_CTRL_ID_PANEL_PLAY, NULL, + FALSE, "play game" }, { - IMG_GFX_GAME_BUTTON_PAUSE2, &game.button.pause2, - GAME_CTRL_ID_PAUSE2, "pause game" + IMG_GFX_GAME_BUTTON_SOUND_MUSIC, &game.button.sound_music, + SOUND_CTRL_ID_MUSIC, &setup.sound_music, + TRUE, "background music on/off" }, { - IMG_GFX_GAME_BUTTON_LOAD, &game.button.load, - GAME_CTRL_ID_LOAD, "load game" + IMG_GFX_GAME_BUTTON_SOUND_LOOPS, &game.button.sound_loops, + SOUND_CTRL_ID_LOOPS, &setup.sound_loops, + TRUE, "sound loops on/off" }, { - IMG_GFX_GAME_BUTTON_SOUND_MUSIC, &game.button.sound_music, - SOUND_CTRL_ID_MUSIC, "background music on/off" + IMG_GFX_GAME_BUTTON_SOUND_SIMPLE, &game.button.sound_simple, + SOUND_CTRL_ID_SIMPLE, &setup.sound_simple, + TRUE, "normal sounds on/off" }, { - IMG_GFX_GAME_BUTTON_SOUND_LOOPS, &game.button.sound_loops, - SOUND_CTRL_ID_LOOPS, "sound loops on/off" + IMG_GFX_GAME_BUTTON_PANEL_SOUND_MUSIC, &game.button.panel_sound_music, + SOUND_CTRL_ID_PANEL_MUSIC, &setup.sound_music, + FALSE, "background music on/off" }, { - IMG_GFX_GAME_BUTTON_SOUND_SIMPLE, &game.button.sound_simple, - SOUND_CTRL_ID_SIMPLE, "normal sounds on/off" + IMG_GFX_GAME_BUTTON_PANEL_SOUND_LOOPS, &game.button.panel_sound_loops, + SOUND_CTRL_ID_PANEL_LOOPS, &setup.sound_loops, + FALSE, "sound loops on/off" + }, + { + IMG_GFX_GAME_BUTTON_PANEL_SOUND_SIMPLE, &game.button.panel_sound_simple, + SOUND_CTRL_ID_PANEL_SIMPLE, &setup.sound_simple, + FALSE, "normal sounds on/off" } }; @@ -15220,8 +15414,10 @@ void CreateGameButtons() int button_type; boolean checked; unsigned int event_mask; - int base_x = (tape.show_game_buttons ? VX : DX); - int base_y = (tape.show_game_buttons ? VY : DY); + boolean allowed_on_tape = gamebutton_info[i].allowed_on_tape; + boolean on_tape = (tape.show_game_buttons && allowed_on_tape); + int base_x = (on_tape ? VX : DX); + int base_y = (on_tape ? VY : DY); int gd_x = gfx->src_x; int gd_y = gfx->src_y; int gd_xp = gfx->src_x + gfx->pressed_xoffset; @@ -15240,7 +15436,9 @@ void CreateGameButtons() } if (id == GAME_CTRL_ID_STOP || + id == GAME_CTRL_ID_PANEL_STOP || id == GAME_CTRL_ID_PLAY || + id == GAME_CTRL_ID_PANEL_PLAY || id == GAME_CTRL_ID_SAVE || id == GAME_CTRL_ID_LOAD) { @@ -15258,10 +15456,8 @@ void CreateGameButtons() else { button_type = GD_TYPE_CHECK_BUTTON; - checked = - ((id == SOUND_CTRL_ID_MUSIC && setup.sound_music) || - (id == SOUND_CTRL_ID_LOOPS && setup.sound_loops) || - (id == SOUND_CTRL_ID_SIMPLE && setup.sound_simple) ? TRUE : FALSE); + checked = (gamebutton_info[i].setup_value != NULL ? + *gamebutton_info[i].setup_value : FALSE); event_mask = GD_EVENT_PRESSED; } @@ -15322,6 +15518,10 @@ static void UnmapGameButtonsAtSamePosition_All() UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_STOP); UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_PAUSE); UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_PLAY); + + UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_PANEL_STOP); + UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_PANEL_PAUSE); + UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_PANEL_PLAY); } } @@ -15360,12 +15560,13 @@ void UnmapUndoRedoButtons() ModifyGadget(game_gadget[GAME_CTRL_ID_PAUSE2], GDI_CHECKED, FALSE, GDI_END); } -void MapGameButtons() +void MapGameButtonsExt(boolean on_tape) { int i; for (i = 0; i < NUM_GAME_BUTTONS; i++) - if (i != GAME_CTRL_ID_UNDO && + if ((!on_tape || gamebutton_info[i].allowed_on_tape) && + i != GAME_CTRL_ID_UNDO && i != GAME_CTRL_ID_REDO) MapGadget(game_gadget[i]); @@ -15374,25 +15575,79 @@ void MapGameButtons() RedrawGameButtons(); } -void UnmapGameButtons() +void UnmapGameButtonsExt(boolean on_tape) { int i; for (i = 0; i < NUM_GAME_BUTTONS; i++) - UnmapGadget(game_gadget[i]); + if (!on_tape || gamebutton_info[i].allowed_on_tape) + UnmapGadget(game_gadget[i]); } -void RedrawGameButtons() +void RedrawGameButtonsExt(boolean on_tape) { int i; for (i = 0; i < NUM_GAME_BUTTONS; i++) - RedrawGadget(game_gadget[i]); + if (!on_tape || gamebutton_info[i].allowed_on_tape) + RedrawGadget(game_gadget[i]); // RedrawGadget() may have set REDRAW_ALL if buttons are defined off-area redraw_mask &= ~REDRAW_ALL; } +void SetGadgetState(struct GadgetInfo *gi, boolean state) +{ + if (gi == NULL) + return; + + gi->checked = state; +} + +void RedrawSoundButtonGadget(int id) +{ + int id2 = (id == SOUND_CTRL_ID_MUSIC ? SOUND_CTRL_ID_PANEL_MUSIC : + id == SOUND_CTRL_ID_LOOPS ? SOUND_CTRL_ID_PANEL_LOOPS : + id == SOUND_CTRL_ID_SIMPLE ? SOUND_CTRL_ID_PANEL_SIMPLE : + id == SOUND_CTRL_ID_PANEL_MUSIC ? SOUND_CTRL_ID_MUSIC : + id == SOUND_CTRL_ID_PANEL_LOOPS ? SOUND_CTRL_ID_LOOPS : + id == SOUND_CTRL_ID_PANEL_SIMPLE ? SOUND_CTRL_ID_SIMPLE : + id); + + SetGadgetState(game_gadget[id2], *gamebutton_info[id2].setup_value); + RedrawGadget(game_gadget[id2]); +} + +void MapGameButtons() +{ + MapGameButtonsExt(FALSE); +} + +void UnmapGameButtons() +{ + UnmapGameButtonsExt(FALSE); +} + +void RedrawGameButtons() +{ + RedrawGameButtonsExt(FALSE); +} + +void MapGameButtonsOnTape() +{ + MapGameButtonsExt(TRUE); +} + +void UnmapGameButtonsOnTape() +{ + UnmapGameButtonsExt(TRUE); +} + +void RedrawGameButtonsOnTape() +{ + RedrawGameButtonsExt(TRUE); +} + void GameUndoRedoExt() { ClearPlayerAction(); @@ -15444,6 +15699,7 @@ static void HandleGameButtonsExt(int id, int button) switch (id) { case GAME_CTRL_ID_STOP: + case GAME_CTRL_ID_PANEL_STOP: if (game_status == GAME_MODE_MAIN) break; @@ -15456,6 +15712,7 @@ static void HandleGameButtonsExt(int id, int button) case GAME_CTRL_ID_PAUSE: case GAME_CTRL_ID_PAUSE2: + case GAME_CTRL_ID_PANEL_PAUSE: if (options.network && game_status == GAME_MODE_PLAYING) { #if defined(NETWORK_AVALIABLE) @@ -15473,6 +15730,7 @@ static void HandleGameButtonsExt(int id, int button) break; case GAME_CTRL_ID_PLAY: + case GAME_CTRL_ID_PANEL_PLAY: if (game_status == GAME_MODE_MAIN) { StartGameActions(options.network, setup.autorecord, level.random_seed); @@ -15516,6 +15774,7 @@ static void HandleGameButtonsExt(int id, int button) break; case SOUND_CTRL_ID_MUSIC: + case SOUND_CTRL_ID_PANEL_MUSIC: if (setup.sound_music) { setup.sound_music = FALSE; @@ -15528,11 +15787,16 @@ static void HandleGameButtonsExt(int id, int button) SetAudioMode(setup.sound); - PlayLevelMusic(); + if (game_status == GAME_MODE_PLAYING) + PlayLevelMusic(); } + + RedrawSoundButtonGadget(id); + break; case SOUND_CTRL_ID_LOOPS: + case SOUND_CTRL_ID_PANEL_LOOPS: if (setup.sound_loops) setup.sound_loops = FALSE; else if (audio.loops_available) @@ -15541,9 +15805,13 @@ static void HandleGameButtonsExt(int id, int button) SetAudioMode(setup.sound); } + + RedrawSoundButtonGadget(id); + break; case SOUND_CTRL_ID_SIMPLE: + case SOUND_CTRL_ID_PANEL_SIMPLE: if (setup.sound_simple) setup.sound_simple = FALSE; else if (audio.sound_available) @@ -15552,6 +15820,9 @@ static void HandleGameButtonsExt(int id, int button) SetAudioMode(setup.sound); } + + RedrawSoundButtonGadget(id); + break; default: @@ -15566,7 +15837,6 @@ static void HandleGameButtons(struct GadgetInfo *gi) void HandleSoundButtonKeys(Key key) { - if (key == setup.shortcut.sound_simple) ClickOnGadget(game_gadget[SOUND_CTRL_ID_SIMPLE], MB_LEFTBUTTON); else if (key == setup.shortcut.sound_loops)