365 lines
14 KiB
Haskell
365 lines
14 KiB
Haskell
module Dodge.Update.Input.InGame (
|
|
updateUseInputInGame,
|
|
) where
|
|
|
|
import Dodge.Terminal
|
|
import Control.Monad
|
|
import Control.Applicative
|
|
import qualified Data.IntMap.Strict as IM
|
|
import Data.List (sort)
|
|
import qualified Data.Map.Strict as M
|
|
import Data.Maybe
|
|
--import Dodge.Base.You
|
|
import Dodge.Button.Event
|
|
import Dodge.Camera
|
|
import Dodge.Creature.Action
|
|
import Dodge.Data.Combine
|
|
import Dodge.Data.Universe
|
|
import Dodge.Default.World
|
|
import Dodge.DisplayInventory
|
|
import Dodge.Event.Test
|
|
import Dodge.InputFocus
|
|
import Dodge.Inventory
|
|
import Dodge.Inventory.Add
|
|
import Dodge.Menu
|
|
import Dodge.Save
|
|
import Dodge.SelectionSections
|
|
import Dodge.SoundLogic
|
|
import Dodge.Update.Input.Text
|
|
import Dodge.WorldPos
|
|
import Geometry
|
|
import LensHelp
|
|
import SDL
|
|
|
|
updateUseInputInGame :: Universe -> Universe
|
|
updateUseInputInGame u = updateFunctionKeys $ case u ^. uvWorld . hud . hudElement of
|
|
DisplayCarte -> over uvWorld updatePressedButtonsCarte u
|
|
DisplayInventory{_subInventory = si} -> case si of
|
|
DisplayTerminal tmid
|
|
| lbinitialpress && inTermFocus w -> u & uvWorld
|
|
%~ doTerminalEffectLB (w ^?! cWorld . lWorld . terminals . ix tmid)
|
|
| inTermFocus (_uvWorld u) -> updateKeysInTerminal tmid u
|
|
| lbinitialpress ->
|
|
u & uvWorld . cWorld . lWorld . terminals . ix tmid . tmInput . tiFocus
|
|
%~ const True
|
|
CombineInventory{_ciSections = sss, _ciSelection = msel}
|
|
| lbinitialpress -> u & uvWorld %~ updateCombineInvClick msel sss
|
|
| inSubInvRegex (u ^. uvWorld) ->
|
|
u
|
|
& uvWorld . hud . hudElement . subInventory
|
|
%~ docombineregexinput sss msel
|
|
& uvWorld . worldEventFlags . at CombineInventoryChange ?~ ()
|
|
_ | inInvRegex (u ^. uvWorld) ->
|
|
u & uvWorld . hud . hudElement %~ dodisplayregexinput (-1)
|
|
& uvWorld . worldEventFlags . at InventoryChange ?~ ()
|
|
& uvWorld %~ setInvPosFromSS
|
|
_ | inCloseRegex (u ^. uvWorld) ->
|
|
u & uvWorld . hud . hudElement %~ dodisplayregexinput' 2
|
|
& uvWorld . worldEventFlags . at InventoryChange ?~ ()
|
|
& uvWorld %~ setInvPosFromSS
|
|
_ -> M.foldlWithKey' updateKeyInGame u pkeys
|
|
where
|
|
w = u ^. uvWorld
|
|
pkeys = u ^. uvWorld . input . pressedKeys
|
|
lbinitialpress = u ^? uvWorld . input . mouseButtons . ix ButtonLeft == Just 0
|
|
dodisplayregexinput x di = fromMaybe di $ do
|
|
sss <- di ^? diSections
|
|
msel <- di ^? diSelection
|
|
filts <- di ^? diInvFilter
|
|
let (sss', msel', filts') = doRegexInput (u ^. uvWorld . input) x sss msel filts
|
|
return $
|
|
di & diSections .~ sss'
|
|
& diSelection .~ msel'
|
|
& diInvFilter .~ filts'
|
|
dodisplayregexinput' x di = fromMaybe di $ do
|
|
sss <- di ^? diSections
|
|
msel <- di ^? diSelection
|
|
filts <- di ^? diCloseFilter
|
|
let (sss', msel', filts') = doRegexInput (u ^. uvWorld . input) x sss msel filts
|
|
return $
|
|
di & diSections .~ sss'
|
|
& diSelection .~ msel'
|
|
& diCloseFilter .~ filts'
|
|
docombineregexinput sss msel ci = fromMaybe ci $ do
|
|
filts <- ci ^? ciFilter
|
|
let (sss', msel', filts') = doRegexInput (u ^. uvWorld . input) (-1) sss msel filts
|
|
return $
|
|
ci & ciSections .~ sss'
|
|
& ciSelection .~ msel'
|
|
& ciFilter .~ filts'
|
|
|
|
updateFunctionKeys :: Universe -> Universe
|
|
updateFunctionKeys u = M.foldlWithKey' updateFunctionKey u
|
|
(u ^. uvWorld . input . pressedKeys)
|
|
|
|
updateFunctionKey :: Universe -> Scancode -> PressType -> Universe
|
|
updateFunctionKey uv sc InitialPress = case sc of
|
|
ScancodeF1 -> useNormalCamera uv
|
|
ScancodeF2 -> pauseAndFloatCam uv
|
|
ScancodeF5 -> doQuicksave uv
|
|
ScancodeF9 -> doQuickload uv
|
|
ScancodeEscape -> pauseGame uv
|
|
_ -> uv
|
|
updateFunctionKey uv _ _ = uv
|
|
|
|
updateCombineInvClick ::
|
|
Maybe (Int, Int) ->
|
|
IM.IntMap (SelectionSection CombinableItem) ->
|
|
World ->
|
|
World
|
|
updateCombineInvClick msel sss w = fromMaybe trydocombination $ do
|
|
(i,j) <- w ^? input . mouseContext . mcoInv
|
|
guard $ i == 0
|
|
str <- fmap (take 5) $ w
|
|
^? hud . hudElement . diSections . ix i . ssItems . ix j . siPictures . ix 0
|
|
return . (worldEventFlags . at CombineInventoryChange ?~ ())
|
|
$ case w ^? hud . hudElement . subInventory . ciFilter . _Just of
|
|
Just (_:xs) | str == xs -> w
|
|
& hud . hudElement . subInventory . ciFilter .~ Nothing
|
|
_ -> w & hud . hudElement . subInventory . ciFilter ?~ ("<" ++ str)
|
|
where
|
|
trydocombination = case w ^? input . mouseContext . mcoCombInv of
|
|
x@(Just (i,_))
|
|
| x /= msel -> w & hud . hudElement . subInventory . ciSelection .~ x
|
|
& worldEventFlags . at CombineInventoryChange ?~ ()
|
|
| i == -1 -> w & hud . hudElement . subInventory . ciFilter .~ Nothing
|
|
& worldEventFlags . at CombineInventoryChange ?~ ()
|
|
_ | (w ^? hud . hudElement . subInventory . ciSelection . _Just . _1) == Just (-1)
|
|
-> w & hud . hudElement . subInventory . ciFilter .~ Nothing
|
|
& worldEventFlags . at CombineInventoryChange ?~ ()
|
|
_ -> (worldEventFlags . at InventoryChange ?~ ()) . maybeExitCombine $
|
|
tryCombine sss msel w
|
|
& worldEventFlags . at CombineInventoryChange ?~ ()
|
|
|
|
updatePressedButtonsCarte :: World -> World
|
|
updatePressedButtonsCarte w = updatePressedButtonsCarte' (_mouseButtons (_input w)) w
|
|
|
|
updatePressedButtonsCarte' :: M.Map MouseButton Int -> World -> World
|
|
updatePressedButtonsCarte' pkeys w
|
|
| isDown ButtonRight =
|
|
w & hud . carteCenter %~ (-.- trans)
|
|
| isDown ButtonLeft =
|
|
w
|
|
& hud . carteRot -~ rot
|
|
& hud . carteZoom *~ czoom
|
|
| otherwise = w
|
|
where
|
|
isDown but = but `M.member` pkeys
|
|
mbutpos but = theinput ^. heldPos . at but
|
|
rot = maybe 0 (angleBetween (_mousePos (_input w))) $ mbutpos SDL.ButtonLeft
|
|
czoom = fromMaybe 1 $ do
|
|
p <- mbutpos SDL.ButtonLeft
|
|
return $ magV (_mousePos theinput) / magV p
|
|
theinput = w ^. input
|
|
trans = fromMaybe 0 $ do
|
|
p <- mbutpos SDL.ButtonRight
|
|
return . rotateV (w ^. hud . carteRot) $
|
|
1 / (w ^. hud . carteZoom) *.* (_mousePos (_input w) -.- p)
|
|
|
|
updateKeysInTerminal :: Int -> Universe -> Universe
|
|
updateKeysInTerminal tmid u =
|
|
u & doTextInputOverUniverse (uvWorld . cWorld . lWorld . terminals . ix tmid . tmInput . tiText)
|
|
& checkEndStatus
|
|
where
|
|
pkeys = u ^. uvWorld . input . pressedKeys
|
|
checkEndStatus
|
|
| pkeys ^. at ScancodeReturn == Just InitialPress =
|
|
over uvWorld (\w -> terminalReturnEffect (w ^?! cWorld . lWorld . terminals . ix tmid) w)
|
|
| otherwise = id
|
|
|
|
updateKeyInGame :: Universe -> Scancode -> PressType -> Universe
|
|
updateKeyInGame uv sc pt = case pt of
|
|
InitialPress -> updateInitialPressInGame uv sc
|
|
LongPress -> updateLongPressInGame uv sc
|
|
_ -> uv
|
|
|
|
updateInitialPressInGame :: Universe -> Scancode -> Universe
|
|
updateInitialPressInGame uv sc = case sc of
|
|
ScancodeSpace -> over uvWorld spaceAction uv
|
|
ScancodeP -> pauseGame uv
|
|
ScancodeF -> over uvWorld youDropItem uv
|
|
ScancodeM -> toggleMap uv
|
|
-- ScancodeR -> over (uvWorld . cWorld . lWorld . creatures . ix 0) crReloadToggle uv
|
|
ScancodeT -> over uvWorld testEvent uv
|
|
ScancodeX -> uv & uvWorld %~ toggleTweakInv
|
|
ScancodeC -> toggleCombineInv uv
|
|
-- the following should be put in a more sensible place
|
|
ScancodeSlash -> uv & uvWorld %~ updateEnterRegex
|
|
ScancodeBackspace -> uv & uvWorld %~ updateBackspaceRegex
|
|
_ -> uv
|
|
|
|
updateLongPressInGame :: Universe -> Scancode -> Universe
|
|
updateLongPressInGame uv sc = case sc of
|
|
ScancodeF -> over uvWorld youDropItem uv
|
|
ScancodeSpace -> over uvWorld spaceAction uv
|
|
_ -> uv
|
|
|
|
doRegexInput ::
|
|
Input ->
|
|
Int ->
|
|
IM.IntMap (SelectionSection a) ->
|
|
Maybe (Int, Int) ->
|
|
Maybe String ->
|
|
(IM.IntMap (SelectionSection a), Maybe (Int, Int), Maybe String)
|
|
doRegexInput inp i sss msel filts
|
|
| backspacetonothing || escapekey = endregex i 0
|
|
| endkeys || endmouse = endregex (i + 1) (j -1)
|
|
| otherwise =
|
|
( sss
|
|
, msel
|
|
, filts & doTextInputOver inp _Just
|
|
)
|
|
where
|
|
endregex a b =
|
|
( sss & ix i . ssItems .~ mempty
|
|
, msel & ssSetCursor (ssLookupDown a b) sss
|
|
, Nothing
|
|
)
|
|
j = fromMaybe 0 $ do
|
|
itms <- sss ^? ix (i + 1) . ssItems
|
|
fst <$> IM.lookupMin itms
|
|
escapekey = ScancodeEscape `M.lookup` pkeys == Just InitialPress
|
|
endkeys =
|
|
any
|
|
((== Just InitialPress) . (`M.lookup` pkeys))
|
|
[ScancodeReturn, ScancodeSlash]
|
|
endmouse = (Just 0 ==) $ inp ^? mouseButtons . ix ButtonLeft
|
|
backspacetonothing =
|
|
filts == Just ""
|
|
&& ScancodeBackspace `M.lookup` pkeys == Just InitialPress
|
|
pkeys = inp ^. pressedKeys
|
|
|
|
updateBackspaceRegex :: World -> World
|
|
updateBackspaceRegex w = case di ^? subInventory of
|
|
Just NoSubInventory{}
|
|
| secfocus (-1) 0 ->
|
|
w & hud . hudElement %~ trybackspace (-1)
|
|
& worldEventFlags . at InventoryChange ?~ ()
|
|
Just NoSubInventory{}
|
|
| secfocus 2 3 ->
|
|
w & hud . hudElement %~ trybackspace'' 2
|
|
& worldEventFlags . at InventoryChange ?~ ()
|
|
Just CombineInventory{} ->
|
|
w & hud . hudElement . subInventory %~ trybackspace' (-1)
|
|
& worldEventFlags . at InventoryChange ?~ ()
|
|
_ -> w
|
|
where
|
|
secfocus a b = fromMaybe False $ do
|
|
i <- di ^? diSelection . _Just . _1
|
|
return $ i == a || i == b
|
|
trybackspace x he = fromMaybe he $ do
|
|
str <- he ^? diInvFilter . _Just
|
|
return $ case str of
|
|
(_ : _) ->
|
|
he & diInvFilter . _Just %~ init
|
|
& diSelection ?~ (x, 0)
|
|
[] -> he & diInvFilter .~ Nothing
|
|
trybackspace'' x he = fromMaybe he $ do
|
|
str <- he ^? diCloseFilter . _Just
|
|
return $ case str of
|
|
(_ : _) ->
|
|
he & diCloseFilter . _Just %~ init
|
|
& diSelection ?~ (x, 0)
|
|
[] -> he & diCloseFilter .~ Nothing
|
|
trybackspace' x ci = fromMaybe ci $ do
|
|
str <- ci ^? ciFilter . _Just
|
|
return $ case str of
|
|
(_ : _) ->
|
|
ci & ciFilter . _Just %~ init
|
|
& ciSelection ?~ (x, 0)
|
|
[] -> ci & ciFilter .~ Nothing
|
|
di = w ^. hud . hudElement
|
|
|
|
updateEnterRegex :: World -> World
|
|
updateEnterRegex w = case w ^? hud . hudElement . subInventory of
|
|
Just NoSubInventory{}
|
|
| secfocus (-1) 0 ->
|
|
w & hud . hudElement . diSelection ?~ (-1, 0)
|
|
& hud . hudElement . diInvFilter %~ enterregex
|
|
Just NoSubInventory{}
|
|
| secfocus 2 3 ->
|
|
w & hud . hudElement . diSelection ?~ (2, 0)
|
|
& hud . hudElement . diCloseFilter %~ enterregex
|
|
Just CombineInventory{} ->
|
|
w & hud . hudElement . subInventory . ciFilter %~ enterregex
|
|
& hud . hudElement . subInventory . ciSelection ?~ (-1, 0)
|
|
_ -> w
|
|
where
|
|
di = w ^. hud . hudElement
|
|
secfocus a b = fromMaybe False $ do
|
|
i <- di ^? diSelection . _Just . _1
|
|
return $ i == a || i == b
|
|
enterregex = (<|> Just "")
|
|
|
|
pauseGame :: Universe -> Universe
|
|
pauseGame u = u & uvScreenLayers .~ [pauseMenu u]
|
|
|
|
spaceAction :: World -> World
|
|
spaceAction w = case w ^. hud . hudElement of
|
|
DisplayCarte -> w & hud . carteCenter .~ theLoc
|
|
DisplayInventory{_subInventory = NoSubInventory{}} -> case selectedCloseObject w of
|
|
Just (Left flit) ->
|
|
pickUpItem 0 flit w
|
|
& worldEventFlags . at InventoryChange ?~ ()
|
|
Just (Right but) ->
|
|
doButtonEvent (_btEvent but) but w
|
|
& worldEventFlags . at InventoryChange ?~ ()
|
|
_ -> w
|
|
DisplayInventory{_subInventory = DisplayTerminal{}} ->
|
|
w & hud . hudElement . subInventory
|
|
.~ NoSubInventory MouseInvNothing
|
|
& worldEventFlags . at InventoryChange ?~ ()
|
|
_ ->
|
|
w & hud . hudElement . subInventory
|
|
.~ NoSubInventory MouseInvNothing
|
|
where
|
|
theLoc =
|
|
doWorldPos
|
|
(w ^?! cWorld . lWorld . seenLocations . ix (w ^. cWorld . lWorld . selLocation) . _1)
|
|
w
|
|
|
|
toggleMap :: Universe -> Universe
|
|
toggleMap u = case u ^. uvWorld . hud . hudElement of
|
|
DisplayCarte ->
|
|
u & uvWorld . hud . hudElement
|
|
.~ DisplayInventory
|
|
{ _subInventory = NoSubInventory MouseInvNothing
|
|
, _diSections = defaultInvSections
|
|
, _diSelection = Nothing
|
|
, _diSelectionExtra = 0
|
|
, -- , _diFilters = IM.fromList [(-1, mempty), (2, mempty)]
|
|
_diInvFilter = mempty
|
|
, _diCloseFilter = mempty
|
|
}
|
|
_ -> u & uvWorld . hud . hudElement .~ DisplayCarte
|
|
|
|
toggleTweakInv :: World -> World
|
|
toggleTweakInv w = case w ^? hud . hudElement . subInventory of
|
|
Just ExamineInventory{} ->
|
|
w
|
|
& thepointer .~ NoSubInventory MouseInvNothing
|
|
_ -> w & thepointer .~ ExamineInventory -- mi
|
|
where
|
|
thepointer = hud . hudElement . subInventory
|
|
|
|
tryCombine ::
|
|
IM.IntMap (SelectionSection CombinableItem) ->
|
|
Maybe (Int, Int) ->
|
|
World ->
|
|
World
|
|
tryCombine sss msel w = fromMaybe w $ do
|
|
(i, j) <- msel
|
|
CombinableItem is it _ <- sss ^? ix i . ssItems . ix j . siPayload
|
|
p <- w ^? cWorld . lWorld . creatures . ix 0 . crPos
|
|
return $
|
|
snd (createItemYou it (foldr (destroyInvItem 0) w (sort is)))
|
|
& cWorld . lWorld . creatures . ix 0 . crHammerPosition .~ HammerDown
|
|
& soundStart InventorySound p wrench1S Nothing
|
|
|
|
maybeExitCombine :: World -> World
|
|
maybeExitCombine w
|
|
| ButtonRight `M.member` (w ^. input . mouseButtons) = w
|
|
| otherwise =
|
|
w & hud . hudElement . subInventory
|
|
.~ NoSubInventory MouseInvNothing
|