283 lines
10 KiB
Haskell
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"
|
|
}
|