module Dodge.Menu ( scodeToChar , popScreen , pushScreen , pauseMenu , gameOverMenu ) where import Dodge.Data import Dodge.Save import Dodge.Config.Update import SDL import SDL.Internal.Numbered import Preload.Update import Dodge.Base.Window import Dodge.SoundLogic import Dodge.LevelGen import Control.Lens import System.Random optionMenu :: ScreenLayer optionMenu = OptionScreen { _scTitle = const "OPTIONS" , _scOptions = optionsOptions , _scDefaultEff = popScreen , _scOptionFlag = NormalOptions } optionsOptions :: [MenuOption] optionsOptions = [ anOption ScancodeV soundMenu "VOLUME" , anOption ScancodeG graphicsMenu "GRAPHICS" , anOption ScancodeP gameplayMenu "GAMEPLAY" , anOption ScancodeD debugMenu "DEBUG OPTIONS" ] where anOption scode submenu t = Toggle scode (pushScreen submenu) (const t) debugMenu :: ScreenLayer debugMenu = OptionScreen { _scTitle = const "OPTIONS:GAMEPLAY" , _scOptions = debugMenuOptions , _scDefaultEff = popScreen . writeConfig , _scOptionFlag = NormalOptions } debugMenuOptions :: [MenuOption] debugMenuOptions = [ doption ScancodeF debug_seconds_frame "SHOW SECONDS/FRAME" _debug_seconds_frame , doption ScancodeC debug_noclip "NOCLIP" _debug_noclip , doption ScancodeS debug_cr_status "SHOW CREATURE STATUS" _debug_cr_status , doption ScancodeV debug_view_boundaries "SHOW VIEW BOUNDARIES" _debug_view_boundaries , doption ScancodeP debug_pathing "SHOW PATHING" _debug_pathing ] where doption scode l t rec = Toggle scode (Just . (config . l %~ not)) (\w -> t ++ ":" ++ show (rec $ _config w)) gameplayMenu :: ScreenLayer gameplayMenu = OptionScreen { _scTitle = const "OPTIONS:GAMEPLAY" , _scOptions = gameplayMenuOptions , _scDefaultEff = popScreen . writeConfig , _scOptionFlag = NormalOptions } gameplayMenuOptions :: [MenuOption] gameplayMenuOptions = [ option ScancodeR rotate_to_wall "ROTATE TO WALL" _rotate_to_wall , option ScancodeS show_sound "SHOW VISUAL SOUNDS" _show_sound ] where option scode l t rec = Toggle scode (Just . (config . l %~ not)) (\w -> t ++ ":" ++ show (rec $ _config w)) soundMenu :: ScreenLayer soundMenu = OptionScreen { _scTitle = const "OPTIONS:VOLUME" , _scOptions = soundMenuOptions , _scDefaultEff = popScreen . writeConfig , _scOptionFlag = NormalOptions } soundMenuOptions :: [MenuOption] soundMenuOptions = [ Toggle2 ScancodeY (master dec . sw) ScancodeU (master inc . sw) (\w -> "MASTER VOLUME:" ++ mavol w) , Toggle2 ScancodeH (soundEffs dec . sw) ScancodeJ (soundEffs inc . sw) (\w -> "EFFECTS VOLUME:" ++ snvol w) , Toggle2 ScancodeN (music dec . sw) ScancodeM (music inc . sw) (\w -> "MUSIC VOLUME:" ++ muvol w) ] where dec x = max 0 (x - 0.1) inc x = min 1 (x + 0.1) --sw w = w & sideEffects %~ (setVol (_config w) : ) sw w = w & sideEffects %~ setVolThen (_config w) master g = Just . (config . volume_master %~ g) soundEffs g = Just . (config . volume_sound %~ g) music g = Just . (config . volume_music %~ g) cfig w = _config w mavol w = f $ _volume_master $ cfig w snvol w = f $ _volume_sound $ cfig w muvol w = f $ _volume_music $ cfig w f x = show (round $ 10 * x :: Int) pushScreen :: ScreenLayer -> World -> Maybe World pushScreen ml w = Just $ w & menuLayers %~ (ml :) popScreen :: World -> Maybe World popScreen = Just . (menuLayers %~ tail) writeConfig :: World -> World writeConfig w = w & sideEffects %~ saveConfig (_config w) graphicsMenu :: ScreenLayer graphicsMenu = OptionScreen { _scTitle = const "OPTIONS:GRAPHICS" , _scOptions = graphicsMenuOptions , _scDefaultEff = popScreen . writeConfig , _scOptionFlag = NormalOptions } graphicsMenuOptions :: [MenuOption] graphicsMenuOptions = [ Toggle ScancodeW (Just . (config . wall_textured %~ not)) wtextstring , Toggle ScancodeS upf resostring , Toggle ScancodeD (Just . (config . cloud_shadows %~ not)) cshadstring ] where wtextstring w = "WALL TEXTURES:" ++ show (_wall_textured $ _config w) resostring w = "RESOLUTION: 1/" ++ show (_resolution_factor $ _config w) upf w = Just $ updateFramebufferSize $ w & config . resolution_factor %~ cycleResolution cshadstring w = "CLOUD SHADOWS:" ++ show (_cloud_shadows $ _config w) cycleResolution :: (Eq a, Num a, Num p) => a -> p cycleResolution 1 = 2 cycleResolution 2 = 4 cycleResolution 4 = 1 cycleResolution _ = 1 gameOverMenu :: ScreenLayer gameOverMenu = OptionScreen { _scTitle = const "GAME OVER" , _scOptions = pauseMenuOptions , _scDefaultEff = Just , _scOptionFlag = GameOverOptions } pauseMenu :: ScreenLayer pauseMenu = OptionScreen { _scTitle = const "PAUSED" , _scOptions = pauseMenuOptions , _scDefaultEff = unpause , _scOptionFlag = NormalOptions } pauseMenuOptions :: [MenuOption] pauseMenuOptions = [ Toggle ScancodeN startNewGame (const "NEW LEVEL") , Toggle ScancodeR (Just . loadSaveSlot LevelStartSlot) (const "RESTART") , Toggle ScancodeO (pushScreen optionMenu ) (const "OPTIONS") , Toggle ScancodeC (pushScreen displayControls) (const "CONTROLS") , InvisibleToggle ScancodeEscape (const Nothing) ] startNewGame :: World -> Maybe World startNewGame w = Just $ w & menuLayers .~ [WaitScreen (const "GENERATING...") 1] & sideEffects .~ uvWorld (uvWorldSideEffects i w) where i = fst $ random (_randGen w) uvWorldSideEffects :: Int -> World -> b -> IO World uvWorldSideEffects i w = const (generateWorldFromSeed i <&> keyConfig .~ _keyConfig w <&> config .~ _config w <&> preloadData .~ _preloadData w) -- this kills save games etc... -- | hacky scodeToChar :: Scancode -> Char scodeToChar = toEnum . (+ 61) . fromIntegral . toNumber --charToScode :: Char -> Scancode --charToScode = Scancode . fromIntegral . (\x -> x - 61) . fromEnum updateFramebufferSize :: World -> World updateFramebufferSize w = w & sideEffects %~ up where (x,y) = (round $ getWindowX w, round $ getWindowY w) divRes = w ^. config . resolution_factor up :: (Universe -> IO Universe) -> Universe -> IO Universe up f w' = do pdata <- pdataResizeUpdate (x `div` divRes) (y `div` divRes) x y (_preloadData (_uvWorld w')) f $ w' & uvWorld . preloadData .~ pdata --levelMenu :: Int -> ScreenLayer --levelMenu x = OptionScreen -- { _scTitle = const $ "LEVEL "++ show x -- , _scOptions = levelMenuOptions -- , _scDefaultEff = unpause . storeLevel -- , _scOptionFlag = NormalOptions -- } unpause :: World -> Maybe World unpause w = Just . resumeSound $ w {_menuLayers = []} displayControls :: ScreenLayer displayControls = ColumnsScreen "CONTROLS" listControls listControls :: [(String,String)] listControls = [("wasd", "MOVEMENT") ,("[rmb]", "AIM") ,("[rmb+lmb]", "SHOOT OR USE ITEM") ,("[wheelscroll]" , "SELECT ITEM" ) ,("[space]" , "PICKUP ITEM" ) ,("m" , "DISPLAY MAP" ) ,("f" , "DROP ITEM" ) ,("c[esc]" , "PAUSE" ) ,("qe" , "ROTATE CAMERA") ,("F5" , "QUICKSAVE") ,("F9" , "QUICKLOAD") ]