diff --git a/doc/ChangeLog.html b/doc/ChangeLog.html index 2b1c9a9f8..9bcca5c74 100644 --- a/doc/ChangeLog.html +++ b/doc/ChangeLog.html @@ -1008,6 +1008,7 @@ <LI>Fixed bug #628947: WC2 Graphic Display Errors (from Jimmy Salmon). <LI>Added smooth scrolling for messages (from Jimmy Salmon). <LI>Fixed bug #657167: Crash on human campaign level 2 (from Jimmy Salmon). + <LI>Added load/save of config options (from Jimmy Salmon). <LI>+++ </UL> </UL> diff --git a/src/include/script.h b/src/include/script.h index 59306c312..d851289fa 100644 --- a/src/include/script.h +++ b/src/include/script.h @@ -117,6 +117,7 @@ extern void CclGcProtect(SCM obj); /// Protect scm object for GC extern void InitCcl(void); /// Initialise ccl extern void LoadCcl(void); /// Load ccl config file extern void SaveCcl(FILE* file); /// Save CCL module +extern void SavePreferences(void); /// Save user preferences extern void CclCommand(const char*); /// Execute a ccl command extern void CclFree(void*); /// Save free diff --git a/src/include/sound.h b/src/include/sound.h index a0b01673d..cc6d97287 100644 --- a/src/include/sound.h +++ b/src/include/sound.h @@ -76,6 +76,7 @@ typedef struct _game_sound_ { ** really turning it off on the server side. */ extern int SoundOff; +extern int MusicOff; /// Music turned off extern GameSound GameSounds; /// Game sound configuration diff --git a/src/sound/music.cpp b/src/sound/music.cpp index 6de3ebc5c..8238661fa 100644 --- a/src/sound/music.cpp +++ b/src/sound/music.cpp @@ -450,6 +450,10 @@ global void PlayMusic(const char* name) } #endif + if (MusicOff) { + return; + } + name = LibraryFileName(name, buffer); #ifdef USE_OGG diff --git a/src/sound/script_sound.cpp b/src/sound/script_sound.cpp index beb0bf252..7c2e5ca0c 100644 --- a/src/sound/script_sound.cpp +++ b/src/sound/script_sound.cpp @@ -409,6 +409,28 @@ local SCM CclSoundOn(void) return SCM_BOOL_F; } +/** +** Turn Off Music (client side) +*/ +local SCM CclMusicOff(void) +{ + StopMusic(); + MusicOff=1; + return SCM_UNSPECIFIED; +} + +/** +** Turn On Music (client side) +** +** @return true if and only if the sound is REALLY turned on +** (uses SoundFildes) +*/ +local SCM CclMusicOn(void) +{ + MusicOff=0; + return SCM_UNSPECIFIED; +} + /** ** Set the cut off distance. ** @@ -516,6 +538,8 @@ global void SoundCclRegister(void) init_subr_0("sound-off",CclSoundOff); init_subr_0("sound-on",CclSoundOn); + init_subr_0("music-off",CclMusicOff); + init_subr_0("music-on",CclMusicOn); init_subr_0("sound-thread",CclSoundThread); init_subr_1("set-global-sound-range!",CclSetGlobalSoundRange); init_lsubr("define-game-sounds",CclDefineGameSounds); @@ -585,6 +609,25 @@ local SCM CclSoundOn(void) return SCM_BOOL_T; } +/** +** Turn Off Music (client side) +*/ +local SCM CclMusicOff(void) +{ + return SCM_UNSPECIFIED; +} + +/** +** Turn On Music (client side) +** +** @return true if and only if the sound is REALLY turned on +** (uses SoundFildes) +*/ +local SCM CclMusicOn(void) +{ + return SCM_UNSPECIFIED; +} + /** ** Set the cut off distance. ** @@ -685,6 +728,8 @@ global void SoundCclRegister(void) gh_new_procedure1_0("set-cd-mode!",CclSetCdMode); gh_new_procedure0_0("sound-off",CclSoundOff); gh_new_procedure0_0("sound-on",CclSoundOn); + gh_new_procedure0_0("music-off",CclMusicOff); + gh_new_procedure0_0("music-on",CclMusicOn); gh_new_procedure0_0("sound-thread",CclSoundThread); gh_new_procedure1_0("set-global-sound-range!",CclSetGlobalSoundRange); gh_new_procedureN("define-game-sounds",CclDefineGameSounds); diff --git a/src/sound/sound.cpp b/src/sound/sound.cpp index 400a1ef78..cf0ebc527 100644 --- a/src/sound/sound.cpp +++ b/src/sound/sound.cpp @@ -59,6 +59,7 @@ ----------------------------------------------------------------------------*/ global int SoundOff; /// True quiet, sound turned off +global int MusicOff; /// Music turned off /** ** Various sounds used in game. diff --git a/src/sound/sound_server.cpp b/src/sound/sound_server.cpp index 6d1323371..2adca92c7 100644 --- a/src/sound/sound_server.cpp +++ b/src/sound/sound_server.cpp @@ -1210,8 +1210,11 @@ global int InitSound(void) */ global int InitSoundServer(void) { - int MapWidth = (TheUI.MapArea.EndX-TheUI.MapArea.X +TileSizeX) / TileSizeX; - int MapHeight = (TheUI.MapArea.EndY-TheUI.MapArea.Y +TileSizeY) / TileSizeY; + int MapWidth; + int MapHeight; + + MapWidth = (TheUI.MapArea.EndX-TheUI.MapArea.X +TileSizeX) / TileSizeX; + MapHeight = (TheUI.MapArea.EndY-TheUI.MapArea.Y +TileSizeY) / TileSizeY; //FIXME: Valid only in shared memory context! DistanceSilent=3*max(MapWidth,MapHeight); DebugLevel2("Distance Silent: %d\n" _C_ DistanceSilent); diff --git a/src/stratagus/script.cpp b/src/stratagus/script.cpp index 0b02e052c..27fb04d09 100644 --- a/src/stratagus/script.cpp +++ b/src/stratagus/script.cpp @@ -55,6 +55,9 @@ #include "trigger.h" #include "settings.h" #include "editor.h" +#include "sound.h" +#include "sound_server.h" +#include "netconnect.h" /*---------------------------------------------------------------------------- -- Variables @@ -117,6 +120,28 @@ local SCM CclSetGameCycle(SCM cycle) return SCM_UNSPECIFIED; } +/** +** Set the video sync speed +*/ +local SCM CclSetVideoSyncSpeed(SCM speed) +{ + VideoSyncSpeed=gh_scm2int(speed); + return SCM_UNSPECIFIED; +} + +/** +** Set the local player name +*/ +local SCM CclSetLocalPlayerName(SCM name) +{ + char *str; + + str = gh_scm2newstr(name,NIL); + strncpy(LocalPlayerName,str,sizeof(LocalPlayerName)-1); + LocalPlayerName[sizeof(LocalPlayerName)-1]='\0'; + return SCM_UNSPECIFIED; +} + /** ** Enable/disable Showing the tips at the start of a level. ** @@ -133,6 +158,25 @@ local SCM CclSetShowTips(SCM flag) return gh_bool2scm(old); } +/** +** Set the current tip number. +** +** @param tip Tip number. +** @return The old tip number. +*/ +local SCM CclSetCurrentTip(SCM tip) +{ + int old; + + old=CurrentTip; + CurrentTip=gh_scm2int(tip); + if (CurrentTip >= MAX_TIPS || Tips[CurrentTip] == NULL) { + CurrentTip = 0; + } + + return gh_int2scm(old); +} + /** ** Add a new tip to the list of tips. ** @@ -577,8 +621,11 @@ global void InitCcl(void) gh_new_procedure0_0("library-path",CclFreeCraftLibraryPath); gh_new_procedure0_0("game-cycle",CclGameCycle); gh_new_procedure1_0("set-game-cycle!",CclSetGameCycle); + gh_new_procedure1_0("set-video-sync-speed!",CclSetVideoSyncSpeed); + gh_new_procedure1_0("set-local-player-name!",CclSetLocalPlayerName); gh_new_procedure1_0("set-show-tips!",CclSetShowTips); + gh_new_procedure1_0("set-current-tip!",CclSetCurrentTip); gh_new_procedure1_0("add-tip",CclAddTip); gh_new_procedure1_0("set-speed-mine!",CclSetSpeedMine); @@ -721,6 +768,146 @@ global void InitCcl(void) print_welcome(); } +/** +** Load user preferences +*/ +local void LoadPreferences1(void) +{ + FILE* fd; + char buf[1024]; + +#ifdef USE_WIN32 + strcpy(buf,"preferences1.ccl"); +#else + sprintf(buf,"%s/%s/preferences1.ccl",getenv("HOME"),FREECRAFT_HOME_PATH); +#endif + + fd=fopen(buf,"r"); + if( fd ) { + fclose(fd); + vload(buf,0,1); + } +} + +/** +** Load user preferences +*/ +local void LoadPreferences2(void) +{ + FILE* fd; + char buf[1024]; + +#ifdef USE_WIN32 + strcpy(buf,"preferences2.ccl"); +#else + sprintf(buf,"%s/%s/preferences2.ccl",getenv("HOME"),FREECRAFT_HOME_PATH); +#endif + + fd=fopen(buf,"r"); + if( fd ) { + fclose(fd); + vload(buf,0,1); + } +} + +/** +** Save user preferences +*/ +global void SavePreferences(void) +{ + FILE* fd; + char buf[1024]; + + // + // preferences1.ccl + // This file is loaded before freecraft.ccl + // + +#ifdef USE_WIN32 + strcpy(buf,"preferences1.ccl"); +#else + sprintf(buf,"%s/%s/preferences1.ccl",getenv("HOME"),FREECRAFT_HOME_PATH); +#endif + + fd=fopen(buf,"w"); + if( !fd ) { + return; + } + + fprintf(fd,";;; -----------------------------------------\n"); + fprintf(fd,";;; $Id$\n"); + + fprintf(fd,"(set-video-resolution! %d %d)\n", VideoWidth, VideoHeight); + + fclose(fd); + + + // + // preferences2.ccl + // This file is loaded after freecraft.ccl + // + +#ifdef USE_WIN32 + strcpy(buf,"preferences2.ccl"); +#else + sprintf(buf,"%s/%s/preferences2.ccl",getenv("HOME"),FREECRAFT_HOME_PATH); +#endif + + fd=fopen(buf,"w"); + if( !fd ) { + return; + } + + fprintf(fd,";;; -----------------------------------------\n"); + fprintf(fd,";;; $Id$\n"); + + // Global options + if( OriginalFogOfWar ) { + fprintf(fd,"(original-fog-of-war)\n"); + } else { + fprintf(fd,"(gray-fog-of-war)\n"); + } + fprintf(fd,"(set-video-fullscreen! #%c)\n", VideoFullScreen ? 't' : 'f'); +#if 0 + // FIXME: Uncomment when this is configurable in the menus + fprintf(fd,"(set-contrast! %d)\n", TheUI.Contrast); + fprintf(fd,"(set-brightness! %d)\n", TheUI.Brightness); + fprintf(fd,"(set-saturation! %d)\n", TheUI.Saturation); +#endif + fprintf(fd,"(set-local-player-name! \"%s\")\n", LocalPlayerName); + + // Game options + fprintf(fd,"(set-show-tips! #%c)\n", ShowTips ? 't' : 'f'); + fprintf(fd,"(set-current-tip! %d)\n", CurrentTip); + + fprintf(fd,"(set-fog-of-war! #%c)\n", !TheMap.NoFogOfWar ? 't' : 'f'); + fprintf(fd,"(set-show-command-key! #%c)\n", ShowCommandKey ? 't' : 'f'); + + // Speeds + fprintf(fd,"(set-video-sync-speed! %d)\n", VideoSyncSpeed); + fprintf(fd,"(set-mouse-scroll-speed! %d)\n", SpeedMouseScroll); + fprintf(fd,"(set-key-scroll-speed! %d)\n", SpeedKeyScroll); + + // Sound options + if( !SoundOff ) { + fprintf(fd,"(sound-on)\n"); + } else { + fprintf(fd,"(sound-off)\n"); + } + fprintf(fd,"(set-sound-volume! %d)\n", GlobalVolume); + if( !MusicOff ) { + fprintf(fd,"(music-on)\n"); + } else { + fprintf(fd,"(music-off)\n"); + } + fprintf(fd,"(set-music-volume! %d)\n", MusicVolume); +#if defined(USE_SDLCD) || defined(USE_LIBCDA) || defined(USE_CDDA) + fprintf(fd,"(set-cd-mode! \"%s\")\n", CDMode); +#endif + + fclose(fd); +} + /** ** Load freecraft config file. */ @@ -735,6 +922,7 @@ global void LoadCcl(void) // Load and evaluate configuration file // CclInConfigFile=1; + LoadPreferences1(); file=LibraryFileName(CclStartFile,buf); ShowLoadProgress("Script %s\n",file); if( (s=strrchr(file,'.')) && s[1]=='C' ) { @@ -742,6 +930,7 @@ global void LoadCcl(void) } else { vload(file,0,1); } + LoadPreferences2(); CclInConfigFile=0; user_gc(SCM_BOOL_F); // Cleanup memory after load } diff --git a/src/stratagus/stratagus.cpp b/src/stratagus/stratagus.cpp index 8e23402c9..5b04f842f 100644 --- a/src/stratagus/stratagus.cpp +++ b/src/stratagus/stratagus.cpp @@ -1200,7 +1200,7 @@ Use it at your own risk.\n\n"); // InitVideo(); // setup video display #ifdef WITH_SOUND - if( InitSound() ) { // setup sound card + if( !SoundOff && InitSound() ) { // setup sound card SoundOff=1; SoundFildes=-1; } diff --git a/src/ui/menus.cpp b/src/ui/menus.cpp index 975cd8082..027aecbc5 100644 --- a/src/ui/menus.cpp +++ b/src/ui/menus.cpp @@ -125,6 +125,7 @@ local void SurrenderConfirmMenu(void); // Global Options local void GlobalOptionsInit(Menuitem *mi); +local void GlobalOptionsExit(Menuitem *mi); local void GlobalOptionsResolutionGem(Menuitem *mi); local void GlobalOptionsFullscreenGem(Menuitem *mi); local void GlobalOptionsFogAlphaGem(Menuitem *mi); @@ -204,6 +205,7 @@ local void EndScenarioQuitMenu(void); // Sound options local void SoundOptionsInit(Menuitem *mi); +local void SoundOptionsExit(Menuitem *mi); local void MasterVolumeHSAction(Menuitem *mi, int i); local void SetMasterPower(Menuitem *mi); local void MusicVolumeHSAction(Menuitem *mi, int i); @@ -215,10 +217,13 @@ local void SetCdModeRandom(Menuitem *mi); // Preferences local void PreferencesInit(Menuitem *mi); +local void PreferencesExit(Menuitem *mi); local void SetFogOfWar(Menuitem *mi); local void SetCommandKey(Menuitem *mi); // Speed options +local void SpeedOptionsInit(Menuitem *mi); +local void SpeedOptionsExit(Menuitem *mi); local void GameSpeedHSAction(Menuitem *mi, int i); local void MouseScrollHSAction(Menuitem *mi, int i); local void KeyboardScrollHSAction(Menuitem *mi, int i); @@ -485,6 +490,7 @@ global void InitMenuFuncHash(void) { // Global Options HASHADD(GlobalOptionsInit,"global-options-init"); + HASHADD(GlobalOptionsExit,"global-options-exit"); HASHADD(GlobalOptionsResolutionGem,"global-options-resolution-gem"); HASHADD(GlobalOptionsFullscreenGem,"global-options-fullscreen-gem"); HASHADD(GlobalOptionsFogAlphaGem,"global-options-fog-alpha-gem"); @@ -563,6 +569,7 @@ global void InitMenuFuncHash(void) { // Sound options HASHADD(SoundOptionsInit,"sound-options-init"); + HASHADD(SoundOptionsExit,"sound-options-exit"); HASHADD(MasterVolumeHSAction,"master-volume-hs-action"); HASHADD(SetMasterPower,"set-master-power"); HASHADD(MusicVolumeHSAction,"music-volume-hs-action"); @@ -574,10 +581,13 @@ global void InitMenuFuncHash(void) { // Preferences HASHADD(PreferencesInit,"preferences-init"); + HASHADD(PreferencesExit,"preferences-exit"); HASHADD(SetFogOfWar,"set-fog-of-war"); HASHADD(SetCommandKey,"set-command-key"); // Speed options + HASHADD(SpeedOptionsInit,"speed-options-init"); + HASHADD(SpeedOptionsExit,"speed-options-exit"); HASHADD(GameSpeedHSAction,"game-speed-hs-action"); HASHADD(MouseScrollHSAction,"mouse-scroll-hs-action"); HASHADD(KeyboardScrollHSAction,"keyboard-scroll-hs-action"); @@ -1555,6 +1565,15 @@ local void SoundOptionsInit(Menuitem *mi __attribute__((unused))) #endif // with sound } +/** +** Exit callback for sound options menu +*/ +local void SoundOptionsExit(Menuitem *mi __attribute__((unused))) +{ + // FIXME: Only save if something changed + SavePreferences(); +} + /** ** Global options menu */ @@ -1603,6 +1622,15 @@ local void GlobalOptionsInit(Menuitem *mi __attribute__((unused))) } } +/** +** Exit callback for global options menu +*/ +local void GlobalOptionsExit(Menuitem *mi __attribute__((unused))) +{ + // FIXME: Only save if something changed + SavePreferences(); +} + /** ** Global options resolution gem callback */ @@ -1635,6 +1663,7 @@ local void GlobalOptionsResolutionGem(Menuitem *mi) VideoWidth = res; VideoHeight = res * 3 / 4; + SavePreferences(); InitVideo(); DestroyCursorBackground(); SetClipping(0,0,VideoWidth-1,VideoHeight-1); @@ -1711,9 +1740,11 @@ local void SetMusicPower(Menuitem *mi __attribute__((unused))) #ifdef WITH_SOUND SCM cb; - if (PlayingMusic == 1) { + if (!MusicOff) { + MusicOff = 1; StopMusic(); } else { + MusicOff = 0; if (CallbackMusic) { cb = gh_symbol2scm("music-stopped"); if (!gh_null_p(symbol_boundp(cb, NIL))) { @@ -1829,12 +1860,20 @@ local void SetCdModeRandom(Menuitem *mi __attribute__((unused))) ** Speed settings menu */ global void SpeedOptionsMenu(void) +{ + ProcessMenu("menu-speed-options", 1); +} + +/** +** Init callback for speed settings menu +*/ +global void SpeedOptionsInit(Menuitem *mi __attribute__((unused))) { Menu *menu; int i; i = 2; - menu = FindMenu("menu-speed-options"); + menu = CurrentMenu; menu->items[i].d.hslider.percent = ((VideoSyncSpeed - MIN_GAME_SPEED) * 100) / (MAX_GAME_SPEED - MIN_GAME_SPEED); if (menu->items[i].d.hslider.percent < 0) { @@ -1852,8 +1891,15 @@ global void SpeedOptionsMenu(void) if (TheUI.KeyScroll == 0) { menu->items[i + 8].d.hslider.percent = 0; } +} - ProcessMenu("menu-speed-options", 1); +/** +** Exit callback for speed settings menu +*/ +global void SpeedOptionsExit(Menuitem *mi __attribute__((unused))) +{ + // FIXME: Only save if something changed + SavePreferences(); } /** @@ -2022,6 +2068,15 @@ local void PreferencesInit(Menuitem *mi __attribute__((unused))) } } +/** +** Preferences menu init callback +*/ +local void PreferencesExit(Menuitem *mi __attribute__((unused))) +{ + // FIXME: Only save if something changed + SavePreferences(); +} + /** ** Show the game options. */ @@ -2261,6 +2316,7 @@ local void TipsExit(Menuitem *mi __attribute__((unused))) { TipsCycleNextTip(); TipsFreeTips(); + SavePreferences(); } /** @@ -2891,6 +2947,9 @@ local void MultiPlayerGameMenu(void) memset(LocalPlayerName, 0, 16); strcpy(LocalPlayerName, NameBuf); + // FIXME: Only save if player name changed + SavePreferences(); + GuiGameStarted = 0; // Here we really go... // ProcessMenu("menu-create-join-menu", 1); diff --git a/src/ui/script_ui.cpp b/src/ui/script_ui.cpp index 8c68b3f2e..6fe90cc21 100644 --- a/src/ui/script_ui.cpp +++ b/src/ui/script_ui.cpp @@ -192,6 +192,39 @@ local SCM CclSetSaturation(SCM saturation) return old; } +/** +** Set the video resolution. +** +** @param width Resolution width. +** @param height Resolution height. +*/ +local SCM CclSetVideoResolution(SCM width,SCM height) +{ + if( CclInConfigFile ) { + VideoWidth=gh_scm2int(width); + VideoHeight=gh_scm2int(height); + } + return SCM_UNSPECIFIED; +} + +/** +** Set the video fullscreen mode. +** +** @param fullscreen True for fullscreen, false for window. +** +** @return Old fullscreen mode +*/ +local SCM CclSetVideoFullscreen(SCM fullscreen) +{ + SCM old; + + old=gh_int2scm(VideoFullScreen); + if( CclInConfigFile ) { + VideoFullScreen=gh_scm2bool(fullscreen); + } + return old; +} + /** ** Default title-screen. ** @@ -3338,6 +3371,9 @@ global void UserInterfaceCclRegister(void) gh_new_procedure1_0("set-brightness!",CclSetBrightness); gh_new_procedure1_0("set-saturation!",CclSetSaturation); + gh_new_procedure2_0("set-video-resolution!",CclSetVideoResolution); + gh_new_procedure1_0("set-video-fullscreen!",CclSetVideoFullscreen); + gh_new_procedure1_0("set-title-screen!",CclSetTitleScreen); gh_new_procedure1_0("set-menu-background!",CclSetMenuBackground); gh_new_procedure1_0("set-menu-background-with-title!",