Files
loop/src/Dodge/Inventory.hs
T
2022-05-21 19:30:51 +01:00

232 lines
8.2 KiB
Haskell

{-# LANGUAGE TupleSections #-}
module Dodge.Inventory
( checkInvSlotsYou
, rmSelectedInvItem
, invSelPos
, invSelSize
, selNumPos
, selNumTextPos
, selNumCol
, selNumSlots
, selNumMidHeight
, augmentedInvSizes
, rmInvItem
, updateCloseObjects
, updateTerminal
, closeObjScrollDir
, closeObjectCol
-- , swapInvDir
, changeInvSel
, changeSwapInvSel
, changeAugInvSel
, crNumFreeSlots
, crInvSize
, selectedCloseObject
)
where
import Dodge.Data
import Dodge.Inventory.CloseObject
import Dodge.Inventory.CheckSlots
import Dodge.Inventory.ItemSpace
import Dodge.Base
import Geometry
--import FoldableHelp
import Padding
import Color
import qualified IntMapHelp as IM
import ListHelp
import LensHelp
--import qualified Data.IntSet as IS
import Data.Maybe
--import Data.List
--import System.Random
-- | after this the item at the inventory position will no longer exist
rmInvItem :: Int -- ^ Creature id
-> Int -- ^ Inventory position
-> World -> World
rmInvItem cid invid w = case w ^? creatures . ix cid . crInv . ix invid . itConsumption . itAmount of
Just x | x > 1 -> w & creatures . ix cid . crInv . ix invid . itConsumption . itAmount %~ subtract 1
_ -> w & creatures . ix cid . crInv %~ f
& creatures . ix cid . crInvSel %~ g
& creatures . ix cid . crLeftInvSel . _Just %~ g
& creatures . ix cid . crInvEquipped %~ IM.delete invid
& creatures . ix cid . crInvEquipped %~ IM.mapKeys g
-- TODO check whether this can be mapKeysMonotonic
where
maxk = fmap fst $ IM.lookupMax $ _crInv $ _creatures w IM.! cid
f inv = let (xs,ys) = IM.split invid inv
in xs `IM.union` IM.mapKeys (subtract 1) ys
g x | x > invid || Just x == maxk = max 0 $ x - 1
| otherwise = x
rmSelectedInvItem :: Int -> World -> World
rmSelectedInvItem cid w = rmInvItem cid (_crInvSel (_creatures w IM.! cid)) w
augmentedInvSizes :: World -> IM.IntMap Int
augmentedInvSizes = bimapAugmentInv itSlotsTaken closeObjectSize
bimapAugmentInv :: (Item -> a) -> (Either FloorItem Button -> a) -> World -> IM.IntMap a
bimapAugmentInv f g w = IM.union
(f <$> yourInv w)
(IM.fromAscList $ zip [length (yourInv w) ..] $ map g $ _closeObjects w)
invSelSize :: Int -> World -> Int
invSelSize i w = fromMaybe 1 $ augmentedInvSizes w IM.!? i
closeObjectSize :: Either FloorItem Button -> Int
closeObjectSize e = case e of
Left flit -> itSlotsTaken $ _flIt flit
Right _ -> 1
closeObjectCol :: Either FloorItem Button -> Color
closeObjectCol e = case e of
Left flit -> _itInvColor $ _flIt flit
Right _ -> yellow
selNumSlots :: Int -> World -> Int
selNumSlots i w = fromMaybe 1 $ augmentedInvSizes w IM.!? i
selNumPos :: Int -> World -> Int
selNumPos i w = splitgap + (foldl' (+) 0 . fst $ IM.split i (augmentedInvSizes w))
where
splitgap
| i < length (yourInv w) = 0
| otherwise = 1
selNumTextPos :: Configuration -> World -> Int -> Point2
selNumTextPos cfig w i = V2 (150 - hw) ( hh + 20 * fromIntegral ipos + 7.5)
where
hh = halfHeight cfig
hw = halfWidth cfig
ipos = selNumPos i w
selNumMidHeight :: Configuration -> World -> Int -> Point2
selNumMidHeight cfig w i = V2 (150 - hw) ( hh + bump - (20 * fromIntegral ipos + 7.5))
where
hh = halfHeight cfig
hw = halfWidth cfig
ipos = selNumPos i w
bump = negate $ 10 * fromIntegral (selNumSlots i w)
selNumCol :: Int -> World -> Color
selNumCol i w = fromMaybe white $ bimapAugmentInv _itInvColor closeObjectCol w IM.!? i
invSelPos :: World -> Int
invSelPos w = splitgap + (foldl' (+) 0 . fst $ IM.split invsel (augmentedInvSizes w))
where
invsel = yourInvSel w
splitgap
| yourInvSel w < length (yourInv w) = 0
| otherwise = 1
updateTerminal :: World -> World
updateTerminal = checkTermDist . updateTerminalLine
checkTermDist :: World -> World
checkTermDist w = case w ^? hud . hudElement . subInventory . termID of
Just btid -> fromMaybe (w & hud . hudElement .~ DisplayInventory NoSubInventory) $ do
btpos <- w ^? buttons . ix btid . btPos
if dist btpos (_crPos $ you w) < 40 then Just w else Nothing
Nothing -> w
updateTerminalLine :: World -> World
updateTerminalLine w = case w ^? hud . hudElement . subInventory . termParams . termFutureLines . ix 0 of
Nothing -> w
Just tl | _tlPause tl > 0 -> w
& hud . hudElement . subInventory . termParams . termFutureLines . ix 0 . tlPause -~ 1
Just (TerminalLineDisplay _ f) -> w
& hud . hudElement . subInventory . termParams . termFutureLines %~ tail
& hud . hudElement . subInventory . termParams . termDisplayedLines .:~ f
Just (TerminalLineEffect _ eff) -> w
& hud . hudElement . subInventory . termParams . termFutureLines %~ tail
& eff (_subInventory . _hudElement $ _hud w)
-- this looks ugly...
updateCloseObjects :: World -> World
updateCloseObjects w = w & closeObjects .~ unionBy closeObjEq oldCloseFiltered currentClose
& creatures . ix (_yourID w) . crInvSel %~ updateinvsel
where
updateinvsel curinvsel
| length (augmentedInvSizes w) <= curinvsel = max 0 $ length (augmentedInvSizes w) - 1
| otherwise = curinvsel
filt = filter $ \obj -> dist ypos (closeObjPos obj) < 40 && hasButtonLOS ypos (closeObjPos obj) w
ypos = _crPos $ you w
activeButtons = map Right
. filter ( (/=) BtNoLabel . _btState)
. IM.elems
$ _buttons w
currentClose = filt $ map Left (IM.elems $ _floorItems w) ++ activeButtons
oldClose = filt $ _closeObjects w
oldCloseFiltered = intersectBy closeObjEq oldClose currentClose
closeObjScrollDir :: Float -> World -> World
closeObjScrollDir x
| x > 0 = over closeObjects rotU
| x < 0 = over closeObjects rotD
| otherwise = id
changeInvSel :: Int -> World -> World
changeInvSel i w
| n == 0 = w
| yourInvSel w < n = w & creatures . ix (_yourID w) . crInvSel %~ (`mod` n) . subtract i
| otherwise = w & creatures . ix (_yourID w) . crInvSel %~ ((+n) . (`mod` numCO) . subtract (i+n))
-- arguably this should jump the invpos into the inventory proper
where
n = length $ _crInv $ _creatures w IM.! _yourID w
numCO = length $ _closeObjects w
changeSwapInvSel :: Int -> World -> World
changeSwapInvSel k w
| n == 0 = w
| yourInvSel w < n = w
& creatures . ix (_yourID w) %~ updatecreature
| otherwise = w & creatures . ix (_yourID w) . crInvSel .~ ico'
& closeObjects %~ swapIndices (i - n) (ico' - n)
where
updatecreature = ( crInv %~ IM.swapKeys (i `mod` n) swapi )
. (crLeftInvSel . _Just %~ updateLeftInvSel)
. (crInvSel %~ (`mod` n) . subtract k)
. (crInvEquipped %~ IM.swapKeys i swapi)
swapi = (i - k) `mod` n
updateLeftInvSel li | i == li = swapi
| swapi == li = i
| otherwise = li
i = _crInvSel $ you w
ico' = ( (i - (k+n)) `mod` numCO ) + n
n = length $ _crInv $ _creatures w IM.! _yourID w
numCO = length $ _closeObjects w
--swapIntSetKeys :: Int -> Int -> IS.IntSet -> IS.IntSet
--swapIntSetKeys i j is
-- | i `IS.member` is && j `IS.member` is = is
-- | i `IS.member` is = j `IS.insert` (i `IS.delete` is)
-- | j `IS.member` is = i `IS.insert` (j `IS.delete` is)
-- | otherwise = is
changeAugInvSel :: Int -> World -> World
changeAugInvSel i w
| n == 0 = w
| otherwise = w & creatures . ix (_yourID w) . crInvSel %~ (`mod` n) . subtract i
where
n = length (yourInv w) + length (_closeObjects w)
bestCloseObjectIndex :: World -> Maybe Int
bestCloseObjectIndex w = findIndex f $ _closeObjects w
where
f (Right _) = True
f (Left flit) = itSlotsTaken (_flIt flit) <= _crInvCapacity ycr - crInvSize ycr
ycr = you w
selectedCloseObject :: World -> Maybe (Int,Either FloorItem Button)
selectedCloseObject w
| invsel >= length inv = selectNthCloseObject w (invsel - length inv)
| otherwise = selectNthCloseObject w =<< bestCloseObjectIndex w
where
invsel = _crInvSel cr
cr = you w
inv = _crInv cr
selectNthCloseObject :: World -> Int -> Maybe (Int,Either FloorItem Button)
selectNthCloseObject w n = (length (yourInv w) + n,) <$> (_closeObjects w !? n)