X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=862c5083d0c2d974b13eeadf6754b9fcfcf162c4;hb=a8167a69b6d4a308f4501b55609ec66dd3082375;hp=9197a84aabf755f9e049e39f81ec22827612d20d;hpb=9f40d091d5c9e5104fa90c881b6cb8ab8470d71d;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 9197a84a..862c5083 100644 --- a/src/game.c +++ b/src/game.c @@ -1016,14 +1016,16 @@ static struct GamePanelControlInfo game_panel_controls[] = #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 GAME_CTRL_ID_TOUCH_STOP 11 +#define GAME_CTRL_ID_TOUCH_PAUSE 12 +#define SOUND_CTRL_ID_MUSIC 13 +#define SOUND_CTRL_ID_LOOPS 14 +#define SOUND_CTRL_ID_SIMPLE 15 +#define SOUND_CTRL_ID_PANEL_MUSIC 16 +#define SOUND_CTRL_ID_PANEL_LOOPS 17 +#define SOUND_CTRL_ID_PANEL_SIMPLE 18 -#define NUM_GAME_BUTTONS 17 +#define NUM_GAME_BUTTONS 19 // forward declaration for internal use @@ -2124,9 +2126,9 @@ static int compareGamePanelOrderInfo(const void *object1, const void *object2) int getPlayerInventorySize(int player_nr) { if (level.game_engine_type == GAME_ENGINE_TYPE_EM) - return level.native_em_level->ply[player_nr]->dynamite; + return game_em.ply[player_nr]->dynamite; else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) - return level.native_sp_level->game_sp->red_disk_count; + return game_sp.red_disk_count; else return stored_player[player_nr].inventory_size; } @@ -2210,32 +2212,32 @@ static void UpdateGameControlValues(void) int time = (game.LevelSolved ? game.LevelSolved_CountingTime : level.game_engine_type == GAME_ENGINE_TYPE_EM ? - level.native_em_level->lev->time : + game_em.lev->time : level.game_engine_type == GAME_ENGINE_TYPE_SP ? - level.native_sp_level->game_sp->time_played : + game_sp.time_played : level.game_engine_type == GAME_ENGINE_TYPE_MM ? game_mm.energy_left : game.no_time_limit ? TimePlayed : TimeLeft); int score = (game.LevelSolved ? game.LevelSolved_CountingScore : level.game_engine_type == GAME_ENGINE_TYPE_EM ? - level.native_em_level->lev->score : + game_em.lev->score : level.game_engine_type == GAME_ENGINE_TYPE_SP ? - level.native_sp_level->game_sp->score : + game_sp.score : level.game_engine_type == GAME_ENGINE_TYPE_MM ? game_mm.score : game.score); int gems = (level.game_engine_type == GAME_ENGINE_TYPE_EM ? - level.native_em_level->lev->required : + game_em.lev->gems_needed : level.game_engine_type == GAME_ENGINE_TYPE_SP ? - level.native_sp_level->game_sp->infotrons_still_needed : + game_sp.infotrons_still_needed : level.game_engine_type == GAME_ENGINE_TYPE_MM ? game_mm.kettles_still_needed : game.gems_still_needed); int exit_closed = (level.game_engine_type == GAME_ENGINE_TYPE_EM ? - level.native_em_level->lev->required > 0 : + game_em.lev->gems_needed > 0 : level.game_engine_type == GAME_ENGINE_TYPE_SP ? - level.native_sp_level->game_sp->infotrons_still_needed > 0 : + game_sp.infotrons_still_needed > 0 : level.game_engine_type == GAME_ENGINE_TYPE_MM ? game_mm.kettles_still_needed > 0 || game_mm.lights_still_needed > 0 : @@ -2275,7 +2277,7 @@ static void UpdateGameControlValues(void) { if (level.game_engine_type == GAME_ENGINE_TYPE_EM) { - if (level.native_em_level->ply[i]->keys & (1 << k)) + if (game_em.ply[i]->keys & (1 << k)) game_panel_controls[GAME_PANEL_KEY_1 + k].value = get_key_element_from_nr(k); } @@ -2303,7 +2305,7 @@ static void UpdateGameControlValues(void) { if (level.game_engine_type == GAME_ENGINE_TYPE_EM) { - if (level.native_em_level->ply[player_nr]->keys & (1 << k)) + if (game_em.ply[player_nr]->keys & (1 << k)) game_panel_controls[GAME_PANEL_KEY_1 + k].value = get_key_element_from_nr(k); } @@ -2904,12 +2906,17 @@ static void InitGameEngine(void) game.use_block_last_field_bug = (game.engine_version < VERSION_IDENT(3,1,1,0)); + /* various special flags and settings for native Emerald Mine game engine */ + game_em.use_single_button = (game.engine_version > VERSION_IDENT(4,0,0,2)); game_em.use_snap_key_bug = (game.engine_version < VERSION_IDENT(4,0,1,0)); + game_em.use_old_explosions = + (game.engine_version < VERSION_IDENT(4,1,4,2)); + // -------------------------------------------------------------------------- // set maximal allowed number of custom element changes per game frame @@ -3248,6 +3255,8 @@ static void InitGameEngine(void) // ---------- initialize graphics engine ------------------------------------ game.scroll_delay_value = (game.forced_scroll_delay_value != -1 ? game.forced_scroll_delay_value : + level.game_engine_type == GAME_ENGINE_TYPE_EM && + !setup.forced_scroll_delay ? 0 : setup.scroll_delay ? setup.scroll_delay_value : 0); game.scroll_delay_value = MIN(MAX(MIN_SCROLL_DELAY, game.scroll_delay_value), MAX_SCROLL_DELAY); @@ -3354,11 +3363,11 @@ void InitGame(void) SetGameStatus(GAME_MODE_PLAYING); if (level_editor_test_game) - FadeSkipNextFadeIn(); + FadeSkipNextFadeOut(); else FadeSetEnterScreen(); - if (CheckIfGlobalBorderOrPlayfieldViewportHasChanged()) + if (CheckFadeAll()) fade_mask = REDRAW_ALL; FadeLevelSoundsAndMusic(); @@ -3367,6 +3376,9 @@ void InitGame(void) FadeOut(fade_mask); + if (level_editor_test_game) + FadeSkipNextFadeIn(); + // needed if different viewport properties defined for playing ChangeViewportPropertiesIfNeeded(); @@ -3401,6 +3413,7 @@ void InitGame(void) player->action = 0; player->effective_action = 0; player->programmed_action = 0; + player->snap_action = 0; player->mouse_action.lx = 0; player->mouse_action.ly = 0; @@ -3737,6 +3750,19 @@ void InitGame(void) game.belt_dir_nr[i] = 3; // not moving, next moving left #if USE_NEW_PLAYER_ASSIGNMENTS + // use preferred player also in local single-player mode + if (!network.enabled && !game.team_mode) + { + int old_index_nr = local_player->index_nr; + int new_index_nr = setup.network_player_nr; + + if (new_index_nr >= 0 && new_index_nr < MAX_PLAYERS) + { + stored_player[old_index_nr].connected_locally = FALSE; + stored_player[new_index_nr].connected_locally = TRUE; + } + } + for (i = 0; i < MAX_PLAYERS; i++) { stored_player[i].connected = FALSE; @@ -3914,6 +3940,7 @@ void InitGame(void) game.centered_player_nr = (network_playing ? local_player->index_nr : -1); game.centered_player_nr_next = game.centered_player_nr; game.set_centered_player = FALSE; + game.set_centered_player_wrap = FALSE; if (network_playing && tape.recording) { @@ -4472,7 +4499,7 @@ static void LevelSolved(void) game.GameOver = TRUE; game.score_final = (level.game_engine_type == GAME_ENGINE_TYPE_EM ? - level.native_em_level->lev->score : + game_em.lev->score : level.game_engine_type == GAME_ENGINE_TYPE_MM ? game_mm.score : game.score); @@ -4503,7 +4530,7 @@ void GameWon(void) int i; // do not start end game actions before the player stops moving (to exit) - if (local_player->MovPos) + if (local_player->active && local_player->MovPos) return; game.LevelSolved_GameWon = TRUE; @@ -5258,11 +5285,8 @@ static void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir, while (scroll_x != new_scroll_x || scroll_y != new_scroll_y) { - int dx = 0, dy = 0; - int fx = FX, fy = FY; - - dx = (new_scroll_x < scroll_x ? +1 : new_scroll_x > scroll_x ? -1 : 0); - dy = (new_scroll_y < scroll_y ? +1 : new_scroll_y > scroll_y ? -1 : 0); + int dx = (new_scroll_x < scroll_x ? +1 : new_scroll_x > scroll_x ? -1 : 0); + int dy = (new_scroll_y < scroll_y ? +1 : new_scroll_y > scroll_y ? -1 : 0); if (dx == 0 && dy == 0) // no scrolling needed at all break; @@ -5270,14 +5294,19 @@ static void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir, scroll_x -= dx; scroll_y -= dy; - fx += dx * TILEX / 2; - fy += dy * TILEY / 2; + // set values for horizontal/vertical screen scrolling (half tile size) + int dir_x = (dx != 0 ? MV_HORIZONTAL : 0); + int dir_y = (dy != 0 ? MV_VERTICAL : 0); + int pos_x = dx * TILEX / 2; + int pos_y = dy * TILEY / 2; + int fx = getFieldbufferOffsetX_RND(dir_x, pos_x); + int fy = getFieldbufferOffsetY_RND(dir_y, pos_y); ScrollLevel(dx, dy); DrawAllPlayers(); // scroll in two steps of half tile size to make things smoother - BlitBitmap(drawto_field, window, fx, fy, SXSIZE, SYSIZE, SX, SY); + BlitScreenToBitmapExt_RND(window, fx, fy); // scroll second step to align at full tile size BlitScreenToBitmap(window); @@ -11044,10 +11073,7 @@ static void CheckSingleStepMode(struct PlayerInfo *player) if (!player->is_moving && !player->is_pushing && !player->is_dropping_pressed) - { TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); - SnapField(player, 0, 0); // stop snapping - } } CheckSaveEngineSnapshot(player); @@ -11221,7 +11247,7 @@ static void CheckLevelTime(void) if (!TimeLeft && setup.time_limit) { if (level.game_engine_type == GAME_ENGINE_TYPE_EM) - level.native_em_level->lev->killed_out_of_time = TRUE; + game_em.lev->killed_out_of_time = TRUE; else for (i = 0; i < MAX_PLAYERS; i++) KillPlayer(&stored_player[i]); @@ -11232,8 +11258,7 @@ static void CheckLevelTime(void) game_panel_controls[GAME_PANEL_TIME].value = TimePlayed; } - level.native_em_level->lev->time = - (game.no_time_limit ? TimePlayed : TimeLeft); + game_em.lev->time = (game.no_time_limit ? TimePlayed : TimeLeft); } if (tape.recording || tape.playing) @@ -11451,13 +11476,14 @@ static void GameActionsExt(void) stored_player[map_player_action[local_player->index_nr]].effective_action = summarized_player_action; + // summarize all actions at centered player in local team mode if (tape.recording && - setup.team_mode && + setup.team_mode && !network.enabled && setup.input_on_focus && game.centered_player_nr != -1) { for (i = 0; i < MAX_PLAYERS; i++) - stored_player[i].effective_action = + stored_player[map_player_action[i]].effective_action = (i == game.centered_player_nr ? summarized_player_action : 0); } @@ -11982,7 +12008,8 @@ void GameActions_RND(void) element == EL_DC_MAGIC_WALL_FULL || element == EL_DC_MAGIC_WALL_ACTIVE || element == EL_DC_MAGIC_WALL_EMPTYING) && - ABS(x-jx) + ABS(y-jy) < ABS(magic_wall_x-jx) + ABS(magic_wall_y-jy)) + ABS(x - jx) + ABS(y - jy) < + ABS(magic_wall_x - jx) + ABS(magic_wall_y - jy)) { magic_wall_x = x; magic_wall_y = y; @@ -12164,11 +12191,17 @@ void GameActions_RND(void) DrawAllPlayers(); PlayAllPlayersSound(); - if (local_player->show_envelope != 0 && local_player->MovPos == 0) + for (i = 0; i < MAX_PLAYERS; i++) { - ShowEnvelope(local_player->show_envelope - EL_ENVELOPE_1); + struct PlayerInfo *player = &stored_player[i]; - local_player->show_envelope = 0; + if (player->show_envelope != 0 && (!player->active || + player->MovPos == 0)) + { + ShowEnvelope(player->show_envelope - EL_ENVELOPE_1); + + player->show_envelope = 0; + } } // use random number generator in every frame to make it less predictable @@ -12499,7 +12532,6 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy) game.centered_player_nr == -1)) { int old_scroll_x = scroll_x, old_scroll_y = scroll_y; - int offset = game.scroll_delay_value; if (!IN_VIS_FIELD(SCREENX(jx), SCREENY(jy))) { @@ -12511,15 +12543,20 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy) } else { + int offset_raw = game.scroll_delay_value; + if (jx != old_jx) // player has moved horizontally { - if ((player->MovDir == MV_LEFT && scroll_x > jx - MIDPOSX + offset) || - (player->MovDir == MV_RIGHT && scroll_x < jx - MIDPOSX - offset)) - scroll_x = jx-MIDPOSX + (scroll_x < jx-MIDPOSX ? -offset : +offset); + int offset = MIN(offset_raw, (SCR_FIELDX - 2) / 2); + int offset_x = offset * (player->MovDir == MV_LEFT ? +1 : -1); + int new_scroll_x = jx - MIDPOSX + offset_x; + + if ((player->MovDir == MV_LEFT && scroll_x > new_scroll_x) || + (player->MovDir == MV_RIGHT && scroll_x < new_scroll_x)) + scroll_x = new_scroll_x; // don't scroll over playfield boundaries - if (scroll_x < SBX_Left || scroll_x > SBX_Right) - scroll_x = (scroll_x < SBX_Left ? SBX_Left : SBX_Right); + scroll_x = MIN(MAX(SBX_Left, scroll_x), SBX_Right); // don't scroll more than one field at a time scroll_x = old_scroll_x + SIGN(scroll_x - old_scroll_x); @@ -12531,13 +12568,16 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy) } else // player has moved vertically { - if ((player->MovDir == MV_UP && scroll_y > jy - MIDPOSY + offset) || - (player->MovDir == MV_DOWN && scroll_y < jy - MIDPOSY - offset)) - scroll_y = jy-MIDPOSY + (scroll_y < jy-MIDPOSY ? -offset : +offset); + int offset = MIN(offset_raw, (SCR_FIELDY - 2) / 2); + int offset_y = offset * (player->MovDir == MV_UP ? +1 : -1); + int new_scroll_y = jy - MIDPOSY + offset_y; + + if ((player->MovDir == MV_UP && scroll_y > new_scroll_y) || + (player->MovDir == MV_DOWN && scroll_y < new_scroll_y)) + scroll_y = new_scroll_y; // don't scroll over playfield boundaries - if (scroll_y < SBY_Upper || scroll_y > SBY_Lower) - scroll_y = (scroll_y < SBY_Upper ? SBY_Upper : SBY_Lower); + scroll_y = MIN(MAX(SBY_Upper, scroll_y), SBY_Lower); // don't scroll more than one field at a time scroll_y = old_scroll_y + SIGN(scroll_y - old_scroll_y); @@ -13451,6 +13491,9 @@ void RemovePlayer(struct PlayerInfo *player) player->present = FALSE; player->active = FALSE; + // required for some CE actions (even if the player is not active anymore) + player->MovPos = 0; + if (!ExplodeField[jx][jy]) StorePlayer[jx][jy] = 0; @@ -14665,78 +14708,78 @@ static void PlayLevelMusic(void) void PlayLevelSound_EM(int xx, int yy, int element_em, int sample) { - int element = (element_em > -1 ? map_element_EM_to_RND(element_em) : 0); + int element = (element_em > -1 ? map_element_EM_to_RND_game(element_em) : 0); int offset = (BorderElement == EL_STEELWALL ? 1 : 0); int x = xx - 1 - offset; int y = yy - 1 - offset; switch (sample) { - case SAMPLE_blank: + case SOUND_blank: PlayLevelSoundElementAction(x, y, element, ACTION_WALKING); break; - case SAMPLE_roll: + case SOUND_roll: PlayLevelSoundElementAction(x, y, element, ACTION_PUSHING); break; - case SAMPLE_stone: + case SOUND_stone: PlayLevelSoundElementAction(x, y, element, ACTION_IMPACT); break; - case SAMPLE_nut: + case SOUND_nut: PlayLevelSoundElementAction(x, y, element, ACTION_IMPACT); break; - case SAMPLE_crack: + case SOUND_crack: PlayLevelSoundElementAction(x, y, element, ACTION_BREAKING); break; - case SAMPLE_bug: + case SOUND_bug: PlayLevelSoundElementAction(x, y, element, ACTION_MOVING); break; - case SAMPLE_tank: + case SOUND_tank: PlayLevelSoundElementAction(x, y, element, ACTION_MOVING); break; - case SAMPLE_android_clone: + case SOUND_android_clone: PlayLevelSoundElementAction(x, y, element, ACTION_DROPPING); break; - case SAMPLE_android_move: + case SOUND_android_move: PlayLevelSoundElementAction(x, y, element, ACTION_MOVING); break; - case SAMPLE_spring: + case SOUND_spring: PlayLevelSoundElementAction(x, y, element, ACTION_IMPACT); break; - case SAMPLE_slurp: + case SOUND_slurp: PlayLevelSoundElementAction(x, y, element, ACTION_EATING); break; - case SAMPLE_eater: + case SOUND_eater: PlayLevelSoundElementAction(x, y, element, ACTION_WAITING); break; - case SAMPLE_eater_eat: + case SOUND_eater_eat: PlayLevelSoundElementAction(x, y, element, ACTION_DIGGING); break; - case SAMPLE_alien: + case SOUND_alien: PlayLevelSoundElementAction(x, y, element, ACTION_MOVING); break; - case SAMPLE_collect: + case SOUND_collect: PlayLevelSoundElementAction(x, y, element, ACTION_COLLECTING); break; - case SAMPLE_diamond: + case SOUND_diamond: PlayLevelSoundElementAction(x, y, element, ACTION_IMPACT); break; - case SAMPLE_squash: + case SOUND_squash: // !!! CHECK THIS !!! #if 1 PlayLevelSoundElementAction(x, y, element, ACTION_BREAKING); @@ -14745,75 +14788,75 @@ void PlayLevelSound_EM(int xx, int yy, int element_em, int sample) #endif break; - case SAMPLE_wonderfall: + case SOUND_wonderfall: PlayLevelSoundElementAction(x, y, element, ACTION_FILLING); break; - case SAMPLE_drip: + case SOUND_drip: PlayLevelSoundElementAction(x, y, element, ACTION_IMPACT); break; - case SAMPLE_push: + case SOUND_push: PlayLevelSoundElementAction(x, y, element, ACTION_PUSHING); break; - case SAMPLE_dirt: + case SOUND_dirt: PlayLevelSoundElementAction(x, y, element, ACTION_DIGGING); break; - case SAMPLE_acid: + case SOUND_acid: PlayLevelSoundElementAction(x, y, element, ACTION_SPLASHING); break; - case SAMPLE_ball: + case SOUND_ball: PlayLevelSoundElementAction(x, y, element, ACTION_DROPPING); break; - case SAMPLE_grow: + case SOUND_slide: PlayLevelSoundElementAction(x, y, element, ACTION_GROWING); break; - case SAMPLE_wonder: + case SOUND_wonder: PlayLevelSoundElementAction(x, y, element, ACTION_ACTIVE); break; - case SAMPLE_door: + case SOUND_door: PlayLevelSoundElementAction(x, y, element, ACTION_PASSING); break; - case SAMPLE_exit_open: + case SOUND_exit_open: PlayLevelSoundElementAction(x, y, element, ACTION_OPENING); break; - case SAMPLE_exit_leave: + case SOUND_exit_leave: PlayLevelSoundElementAction(x, y, element, ACTION_PASSING); break; - case SAMPLE_dynamite: + case SOUND_dynamite: PlayLevelSoundElementAction(x, y, element, ACTION_DROPPING); break; - case SAMPLE_tick: + case SOUND_tick: PlayLevelSoundElementAction(x, y, element, ACTION_ACTIVE); break; - case SAMPLE_press: + case SOUND_press: PlayLevelSoundElementAction(x, y, element, ACTION_ACTIVATING); break; - case SAMPLE_wheel: + case SOUND_wheel: PlayLevelSoundElementAction(x, y, element, ACTION_ACTIVE); break; - case SAMPLE_boom: + case SOUND_boom: PlayLevelSoundElementAction(x, y, element, ACTION_EXPLODING); break; - case SAMPLE_die: + case SOUND_die: PlayLevelSoundElementAction(x, y, element, ACTION_DYING); break; - case SAMPLE_time: + case SOUND_time: PlaySound(SND_GAME_RUNNING_OUT_OF_TIME); break; @@ -14973,7 +15016,12 @@ void RequestQuitGameExt(boolean skip_request, boolean quick_quit, char *message) { // closing door required in case of envelope style request dialogs if (!skip_request) + { + // prevent short reactivation of overlay buttons while closing door + SetOverlayActive(FALSE); + CloseDoor(DOOR_CLOSE_1); + } if (network.enabled) SendToServer_StopPlaying(NETWORK_STOP_BY_PLAYER); @@ -15437,93 +15485,104 @@ static struct int gadget_id; boolean *setup_value; boolean allowed_on_tape; + boolean is_touch_button; char *infotext; } gamebutton_info[NUM_GAME_BUTTONS] = { { IMG_GFX_GAME_BUTTON_STOP, &game.button.stop, GAME_CTRL_ID_STOP, NULL, - TRUE, "stop game" + TRUE, FALSE, "stop game" }, { IMG_GFX_GAME_BUTTON_PAUSE, &game.button.pause, GAME_CTRL_ID_PAUSE, NULL, - TRUE, "pause game" + TRUE, FALSE, "pause game" }, { IMG_GFX_GAME_BUTTON_PLAY, &game.button.play, GAME_CTRL_ID_PLAY, NULL, - TRUE, "play game" + TRUE, FALSE, "play game" }, { IMG_GFX_GAME_BUTTON_UNDO, &game.button.undo, GAME_CTRL_ID_UNDO, NULL, - TRUE, "undo step" + TRUE, FALSE, "undo step" }, { IMG_GFX_GAME_BUTTON_REDO, &game.button.redo, GAME_CTRL_ID_REDO, NULL, - TRUE, "redo step" + TRUE, FALSE, "redo step" }, { IMG_GFX_GAME_BUTTON_SAVE, &game.button.save, GAME_CTRL_ID_SAVE, NULL, - TRUE, "save game" + TRUE, FALSE, "save game" }, { IMG_GFX_GAME_BUTTON_PAUSE2, &game.button.pause2, GAME_CTRL_ID_PAUSE2, NULL, - TRUE, "pause game" + TRUE, FALSE, "pause game" }, { IMG_GFX_GAME_BUTTON_LOAD, &game.button.load, GAME_CTRL_ID_LOAD, NULL, - TRUE, "load game" + TRUE, FALSE, "load game" }, { IMG_GFX_GAME_BUTTON_PANEL_STOP, &game.button.panel_stop, GAME_CTRL_ID_PANEL_STOP, NULL, - FALSE, "stop game" + FALSE, FALSE, "stop game" }, { IMG_GFX_GAME_BUTTON_PANEL_PAUSE, &game.button.panel_pause, GAME_CTRL_ID_PANEL_PAUSE, NULL, - FALSE, "pause game" + FALSE, FALSE, "pause game" }, { IMG_GFX_GAME_BUTTON_PANEL_PLAY, &game.button.panel_play, GAME_CTRL_ID_PANEL_PLAY, NULL, - FALSE, "play game" + FALSE, FALSE, "play game" + }, + { + IMG_GFX_GAME_BUTTON_TOUCH_STOP, &game.button.touch_stop, + GAME_CTRL_ID_TOUCH_STOP, NULL, + FALSE, TRUE, "stop game" + }, + { + IMG_GFX_GAME_BUTTON_TOUCH_PAUSE, &game.button.touch_pause, + GAME_CTRL_ID_TOUCH_PAUSE, NULL, + FALSE, TRUE, "pause game" }, { IMG_GFX_GAME_BUTTON_SOUND_MUSIC, &game.button.sound_music, SOUND_CTRL_ID_MUSIC, &setup.sound_music, - TRUE, "background music on/off" + TRUE, FALSE, "background music on/off" }, { IMG_GFX_GAME_BUTTON_SOUND_LOOPS, &game.button.sound_loops, SOUND_CTRL_ID_LOOPS, &setup.sound_loops, - TRUE, "sound loops on/off" + TRUE, FALSE, "sound loops on/off" }, { IMG_GFX_GAME_BUTTON_SOUND_SIMPLE, &game.button.sound_simple, SOUND_CTRL_ID_SIMPLE, &setup.sound_simple, - TRUE, "normal sounds on/off" + TRUE, FALSE, "normal sounds 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" + FALSE, FALSE, "background music 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" + FALSE, 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" + FALSE, FALSE, "normal sounds on/off" } }; @@ -15540,10 +15599,11 @@ void CreateGameButtons(void) int button_type; boolean checked; unsigned int event_mask; + boolean is_touch_button = gamebutton_info[i].is_touch_button; 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 base_x = (is_touch_button ? 0 : on_tape ? VX : DX); + int base_y = (is_touch_button ? 0 : 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; @@ -15552,6 +15612,8 @@ void CreateGameButtons(void) int gd_ya = gfx->src_y + gfx->active_yoffset; int gd_xap = gfx->src_x + gfx->active_xoffset + gfx->pressed_xoffset; int gd_yap = gfx->src_y + gfx->active_yoffset + gfx->pressed_yoffset; + int x = (is_touch_button ? pos->x : GDI_ACTIVE_POS(pos->x)); + int y = (is_touch_button ? pos->y : GDI_ACTIVE_POS(pos->y)); int id = i; if (gfx->bitmap == NULL) @@ -15563,6 +15625,7 @@ void CreateGameButtons(void) if (id == GAME_CTRL_ID_STOP || id == GAME_CTRL_ID_PANEL_STOP || + id == GAME_CTRL_ID_TOUCH_STOP || id == GAME_CTRL_ID_PLAY || id == GAME_CTRL_ID_PANEL_PLAY || id == GAME_CTRL_ID_SAVE || @@ -15590,8 +15653,8 @@ void CreateGameButtons(void) gi = CreateGadget(GDI_CUSTOM_ID, id, GDI_IMAGE_ID, graphic, GDI_INFO_TEXT, gamebutton_info[i].infotext, - GDI_X, base_x + GDI_ACTIVE_POS(pos->x), - GDI_Y, base_y + GDI_ACTIVE_POS(pos->y), + GDI_X, base_x + x, + GDI_Y, base_y + y, GDI_WIDTH, gfx->width, GDI_HEIGHT, gfx->height, GDI_TYPE, button_type, @@ -15602,6 +15665,7 @@ void CreateGameButtons(void) GDI_ALT_DESIGN_UNPRESSED, gfx->bitmap, gd_xa, gd_ya, GDI_ALT_DESIGN_PRESSED, gfx->bitmap, gd_xap, gd_yap, GDI_DIRECT_DRAW, FALSE, + GDI_OVERLAY_TOUCH_BUTTON, is_touch_button, GDI_EVENT_MASK, event_mask, GDI_CALLBACK_ACTION, HandleGameButtons, GDI_END); @@ -15672,8 +15736,6 @@ void MapUndoRedoButtons(void) MapGadget(game_gadget[GAME_CTRL_ID_UNDO]); MapGadget(game_gadget[GAME_CTRL_ID_REDO]); - - ModifyGadget(game_gadget[GAME_CTRL_ID_PAUSE2], GDI_CHECKED, TRUE, GDI_END); } void UnmapUndoRedoButtons(void) @@ -15683,8 +15745,22 @@ void UnmapUndoRedoButtons(void) MapGameButtonsAtSamePosition(GAME_CTRL_ID_UNDO); MapGameButtonsAtSamePosition(GAME_CTRL_ID_REDO); +} + +void ModifyPauseButtons(void) +{ + static int ids[] = + { + GAME_CTRL_ID_PAUSE, + GAME_CTRL_ID_PAUSE2, + GAME_CTRL_ID_PANEL_PAUSE, + GAME_CTRL_ID_TOUCH_PAUSE, + -1 + }; + int i; - ModifyGadget(game_gadget[GAME_CTRL_ID_PAUSE2], GDI_CHECKED, FALSE, GDI_END); + for (i = 0; ids[i] > -1; i++) + ModifyGadget(game_gadget[ids[i]], GDI_CHECKED, tape.pausing, GDI_END); } static void MapGameButtonsExt(boolean on_tape) @@ -15718,9 +15794,6 @@ static void RedrawGameButtonsExt(boolean on_tape) for (i = 0; i < NUM_GAME_BUTTONS; 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; } static void SetGadgetState(struct GadgetInfo *gi, boolean state) @@ -15827,6 +15900,7 @@ static void HandleGameButtonsExt(int id, int button) { case GAME_CTRL_ID_STOP: case GAME_CTRL_ID_PANEL_STOP: + case GAME_CTRL_ID_TOUCH_STOP: if (game_status == GAME_MODE_MAIN) break; @@ -15840,6 +15914,7 @@ static void HandleGameButtonsExt(int id, int button) case GAME_CTRL_ID_PAUSE: case GAME_CTRL_ID_PAUSE2: case GAME_CTRL_ID_PANEL_PAUSE: + case GAME_CTRL_ID_TOUCH_PAUSE: if (network.enabled && game_status == GAME_MODE_PLAYING) { if (tape.pausing)