{- | Deals with keyboard events. -} module Dodge.Event.Keyboard ( handleKeyboardEvent ) where import Dodge.Data import Dodge.Save import Dodge.Base import Dodge.Creature.Action import Dodge.Config.KeyConfig import Dodge.Event.Test import Dodge.Event.Menu import Dodge.Menu import qualified Data.IntMap.Strict as IM import SDL import Data.Maybe import qualified Data.Set as S import Control.Lens {- | Handles keyboard press and release. On release, remove scancode from the 'Set' of pressed keys. On press, adds the scancode, and perhaps applies a direct effect: see 'handlePressedKeyInGame'. -} handleKeyboardEvent :: KeyboardEventData -> World -> Maybe World handleKeyboardEvent kev w = case keyboardEventKeyMotion kev of Released -> Just $ w & keys %~ S.delete kcode Pressed -> handlePressedKey (keyboardEventRepeat kev) kcode (w & keys %~ S.insert kcode) where kcode = (keysymScancode . keyboardEventKeysym) kev handlePressedKey :: Bool -> Scancode -> World -> Maybe World handlePressedKey True _ w = Just w handlePressedKey _ ScancodeF5 w = Just $ doQuicksave w handlePressedKey _ ScancodeF9 w = Just $ loadSaveSlot QuicksaveSlot w handlePressedKey _ ScancodeSemicolon w = Just $ gotoTerminal w handlePressedKey _ scode w | null (_menuLayers w) = handlePressedKeyInGame scode w | otherwise = handlePressedKeyInMenu (head $ _menuLayers w) scode w handlePressedKeyInGame :: Scancode -> World -> Maybe World handlePressedKeyInGame scode w | scode == escapeKey (_keyConfig w) = Nothing | scode == pauseKey (_keyConfig w) = Just $ pauseGame $ escapeMap w | scode == dropItemKey (_keyConfig w) = Just $ youDropItem w | scode == toggleMapKey (_keyConfig w) = Just $ toggleMap w | scode == reloadKey (_keyConfig w) = Just $ fromMaybe w $ startReloadingWeapon (you w) w | scode == testEventKey (_keyConfig w) = Just $ testEvent w | scode == spaceActionKey (_keyConfig w) = Just $ spaceAction w | scode == rotateCameraPlusKey (_keyConfig w) = Just $ w & cameraRot +~ 0.01 | scode == rotateCameraMinusKey (_keyConfig w) = Just $ w & cameraRot -~ 0.01 | scode == ScancodeX = Just $ w & inventoryMode %~ toggleInv TweakInventory | scode == ScancodeC = Just $ w & inventoryMode %~ toggleInv CombineInventory | scode == ScancodeI = Just $ w & inventoryMode %~ toggleInv InspectInventory handlePressedKeyInGame _ w = Just w toggleInv :: InventoryMode -> InventoryMode -> InventoryMode toggleInv x y | x == y = TopInventory | otherwise = x gotoTerminal :: World -> World gotoTerminal w = case _menuLayers w of (InputScreen _ : _ ) -> w _ -> w & menuLayers %~ (InputScreen [] :) spaceAction :: World -> World spaceAction w = if _carteDisplay w then w & carteCenter .~ theLoc else case (_inventoryMode w, listToMaybe $ _closeObjects w) of (TopInventory,Just (Left flit)) -> pickUpItem 0 flit w (TopInventory,Just (Right but)) -> updateTopCloseObject (_btID but) $ _btEvent but but w _ -> w & inventoryMode .~ TopInventory where theLoc = fst (_seenLocations w IM.! _selLocation w) w updateTopCloseObject i w' = w' & closeObjects %~ ( Right (_buttons w' IM.! i) : ) . tail pauseGame :: World -> World pauseGame w = w {_menuLayers = [pauseMenu]} toggleMap :: World -> World toggleMap w = w & carteDisplay %~ not escapeMap :: World -> World escapeMap w = w & carteDisplay .~ False