Files
loop/src/Dodge/DisplayInventory.hs
T

283 lines
10 KiB
Haskell

--{-# LANGUAGE TupleSections #-}
--{-# OPTIONS_GHC -fno-full-laziness #-}
module Dodge.DisplayInventory (
toggleCombineInv,
updateInventoryPositioning,
updateCombinePositioning,
) where
import Dodge.Data.DoubleTree
import Control.Lens
import Dodge.Inventory.SelectionList
import Control.Monad
import qualified Data.IntMap.Strict as IM
import Data.Maybe
import Dodge.Base.You
import Dodge.Combine
import Dodge.Data.Combine
import Dodge.Data.Config
import Dodge.Data.SelectionList
import Dodge.Data.Universe
import Dodge.Inventory.CheckSlots
import Dodge.ListDisplayParams
import Dodge.SelectionList
import Dodge.Item.Grammar
import ListHelp
import Picture.Base
import Regex
toggleCombineInv :: Universe -> Universe
toggleCombineInv uv = case uv ^? uvWorld . hud . hudElement . subInventory of
Just CombineInventory{} -> uv & uvWorld . hud . hudElement . subInventory
.~ NoSubInventory MouseInvNothing Nothing
_ -> uv & uvWorld %~ enterCombineInv (uv ^. uvConfig)
updateCombinePositioning :: Universe -> Universe
updateCombinePositioning u =
u & uvWorld . hud . hudElement . subInventory . ciSections
%~ updateCombineSections (_uvWorld u) (_uvConfig u)
updateCombineSections :: World -> Configuration -> SelectionSections CombinableItem -> SelectionSections CombinableItem
updateCombineSections w cfig sss =
sss & sssSections
%~ updateSectionsPositioning
mselpos
availablelines
[(0, showncombs), (-1, filtinv)]
where
mselpos = w ^? hud . hudElement . subInventory . ciSelection . _Just
availablelines = getAvailableListLines secondColumnParams cfig
allcombs = IM.fromDistinctAscList $ zip [0 ..] $ combineList w
filtcombs = fromMaybe allcombs $ do
str <- mstr
invitms <- w ^? hud . hudElement . diSections . sssSections . ix 0 . ssItems
return $ IM.filter (flip (andOrRegex $ regexCombs invitms) str) allcombs
showncombs
| null filtcombs = IM.singleton 0 $ SelectionInfo ["No possible combinations"] 1 False white 0
| otherwise = filtcombs
filtinv = fromMaybe mempty $ do
str <- mstr
return $
IM.singleton
0
(SelectionInfo ["COMBINATIONS FILTER: " ++ str, numfiltitems] 2 True white 0)
mstr = w ^? hud . hudElement . subInventory . ciSections . sssExtra . sssFilters . ix (-1) . _Just
numfiltitems = " " ++ show (length allcombs - length filtcombs) ++ " FILTERED"
regexCombs :: IM.IntMap (SelectionItem ()) -> SelectionItem CombinableItem -> String -> Bool
regexCombs inv ci str = case str of
'<' : str' -> f str' ci
_ -> (regexList str . _siPictures) ci
where
f str' si = any (g str') (_ciInvIDs $ _siPayload si)
g str' i = fromMaybe False $ do
si' <- inv ^? ix i
return $ regexList str' $ _siPictures si'
andOrRegex :: (a -> String -> Bool) -> a -> String -> Bool
andOrRegex f x str = all (orRegex f x) (wordsBy '&' str)
orRegex :: (a -> String -> Bool) -> a -> String -> Bool
orRegex f x str = case words str of
[] -> True
xs -> any (f x) xs
updateInventoryPositioning :: Universe -> Universe
updateInventoryPositioning u =
u & uvWorld . hud . hudElement . diSections
%~ updateDisplaySections (_uvWorld u) (_uvConfig u)
updateDisplaySections
:: World
-> Configuration
-> SelectionSections ()
-> SelectionSections ()
updateDisplaySections w cfig sss =
sss & sssSections
%~ updateSectionsPositioning
mselpos
availablelines
addorder
where
mselpos = w ^? hud . hudElement . diSelection . _Just
addorder = case mselpos of
Just (-1, _) -> reverse [filtinv, filtclose, invx, youx, closex]
Just (0, _) -> reverse [filtinv, filtclose, invx, youx, closex]
Just (1, _) -> reverse [filtinv, filtclose, invx, youx, closex]
Just (2, _) -> reverse [filtinv, filtclose, closex, invx, youx]
_ -> reverse [filtinv, filtclose, closex, invx, youx]
(filtinv, invx) = filtpair (-1) invitems' "INV. "
(filtclose, closex) = filtpair 2 coitems' "NEARBY "
youx = (1, youitems)
youitems = IM.singleton 0 $ SelectionItem [thetext] 1 True invDimColor 2 ()
thetext = displayFreeSlots nfreeslots
availablelines = getAvailableListLines (invDisplayParams w) cfig
coitems' =
IM.fromDistinctAscList . zip [0 ..] $
map closeObjectToSelectionItem (w ^. hud . closeObjects)
invitems' = IM.mapWithKey (\k (y,x) -> invSelectionItem cr k (x ^. locLDT . ldtValue) y)
invlocs
cr = you w
invlocs = allInvLocs $ _crInv (you w)
nfreeslots = crNumFreeSlots cr
filtpair i itms filtdescription =
( (i, filtsis)
, (i + 1, itms')
)
where
mstr = w ^? hud . hudElement . diSections . sssExtra . sssFilters . ix i . _Just
filtsis = fromMaybe mempty $ do
str <- mstr
return $
IM.singleton
0
(SelectionInfo [filtdescription ++ "FILTER: " ++ str, numfiltitems] 2 True white 0)
itms' = fromMaybe itms $ do
str <- mstr
return $ IM.filter (plainRegex str) itms
numfiltitems = " " ++ show (length itms - length itms') ++ " FILTERED"
invDimColor :: Color
invDimColor = greyN 0.7
plainRegex :: String -> SelectionItem a -> Bool
plainRegex = flip $ andOrRegex (\si str -> regexList str (_siPictures si))
displayFreeSlots :: Int -> String
displayFreeSlots x = case x of
0 -> "INVENTORY FULL"
1 -> "1 FREE SLOT"
_ -> show x ++ " FREE SLOTS"
updateSectionsPositioning ::
Maybe (Int, Int) ->
Int ->
[(Int, IM.IntMap (SelectionItem a))] ->
IM.IntMap (SelectionSection a) ->
IM.IntMap (SelectionSection a)
updateSectionsPositioning _ _ [] _ = mempty
updateSectionsPositioning mselpos allavailablelines ((k, y) : xs) sss =
IM.insert k ss previoussections
where
mscel = do
(i, j) <- mselpos
guard $ i == k
return j
ss = updateSection y mscel linesleft x
x = sss ^?! ix k
availablelines = allavailablelines - _ssMinSize x
linesleft = allavailablelines - sum (linestaken <$> previoussections)
linestaken ss' = max (length $ _ssShownItems ss') (_ssMinSize ss')
previoussections = updateSectionsPositioning mselpos availablelines xs sss
updateSection ::
IM.IntMap (SelectionItem a) ->
Maybe Int ->
Int ->
SelectionSection a ->
SelectionSection a
updateSection sis mcsel availablelines ss =
ss
& ssItems .~ sis
& ssCursor .~ scurs
& ssOffset .~ offset
& ssShownItems .~ shownitems
where
oldoffset = ss ^. ssOffset
scurs = do
csel <- mcsel
(_, si) <- IM.lookupGE csel sis -- this is not right?
let cpos = sum (fmap _siHeight . fst . IM.split csel $ sis)
csize = length $ _siPictures si
ccolor = _siColor si
return $ SectionCursor (cpos - offset) csize ccolor
nocursoroffset =
if length allstrings - oldoffset <= availablelines
then max 0 (length allstrings - availablelines)
else oldoffset
offset = fromMaybe nocursoroffset $ do
csel <- mcsel
maxcsel <- fst <$> IM.lookupMax sis
si <- sis ^? ix csel
let xselsize = length $ _siPictures si
return $ case sum $ fmap (length . _siPictures) . fst . IM.split csel $ sis of
pos | pos == 0 || length allstrings <= availablelines ->
0
pos | pos - 1 < oldoffset ->
pos - 1
pos | maxcsel == csel ->
pos - availablelines + xselsize
pos | pos + 1 + xselsize - availablelines > oldoffset ->
pos - availablelines + 1 + xselsize
_ | length allstrings - oldoffset < availablelines ->
length allstrings - availablelines
_ -> oldoffset
tweakfirst (x : xs)
| offset > 0 =
translate 0 (-100) (color moreupcolor $ text (theindent ++ replicate 15 '^')) :
map h xs
| otherwise = map h (x : xs)
tweakfirst [] = []
moreupcolor = fromMaybe white $ allstrings ^? ix offset . _1
shownitems
| length shownstrings > availablelines =
tweakfirst (take (availablelines - 1) shownstrings)
++ [translate 0 100 . color moredowncolor . textVMirror $ theindent ++ replicate 15 '^']
| otherwise = tweakfirst shownstrings
moredowncolor = fromMaybe white $ allstrings ^? ix (offset + availablelines - 1) . _1
allstrings = listSelectionColorPicture sis
shownstrings = drop offset allstrings
h (_, str) = translate (fromIntegral (_ssIndent ss) * 100) 0 str
theindent = replicate (_ssIndent ss) ' '
listSelectionColorPicture :: Foldable t => t (SelectionItem a) -> [(Color,Picture)]
listSelectionColorPicture = foldMap f
where
f si = map g (_siPictures si)
where
indent = 100 * fromIntegral (_siOffX si)
g str = (_siColor si,translate indent 0 . color (_siColor si) $ text str)
enterCombineInv :: Configuration -> World -> World
enterCombineInv cfig w = w & hud . hudElement . subInventory .~ CombineInventory sss selpos
where
cm' = IM.fromDistinctAscList . zip [0 ..] $ combineList w
cm
| null cm' = IM.singleton 0 $ SelectionInfo ["No possible combinations"] 1 False white 0
| otherwise = cm'
sss =
SelectionSections
{ _sssSections = IM.fromDistinctAscList [(-1, filtsection), (0, combsection)]
, _sssExtra =
SSSExtra
{ _sssFilters = IM.singleton (-1) Nothing
}
}
selpos
| null cm' = Nothing
| otherwise = Just (0, 0)
availablelines = getAvailableListLines secondColumnParams cfig
filtsection =
SelectionSection
{ _ssItems = mempty
, _ssCursor = Nothing
, _ssMinSize = 0
, _ssOffset = 0
, _ssShownItems = mempty
, _ssIndent = 0
, _ssDescriptor = "COMB FILTER"
}
combsection = updateSection cm (Just 0) availablelines SelectionSection
{ _ssItems = cm
, _ssCursor = do
(_, si) <- IM.lookupMin cm
return $ SectionCursor 0 (_siHeight si) (_siColor si)
, _ssMinSize = 5
, _ssOffset = 0
, _ssShownItems = mempty
, _ssIndent = 0
, _ssDescriptor = "COMBINATIONS"
}