Files
loop/src/Dodge/Update/Input/InGame.hs
T
2024-11-10 18:26:30 +00:00

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