Files
loop/src/Dodge/Inventory.hs
T

227 lines
7.3 KiB
Haskell

--{-# LANGUAGE TupleSections #-}
module Dodge.Inventory (
rmInvItem,
destroyInvItem,
updateCloseObjects,
changeSwapSel,
invSetSelection,
invSetSelectionPos,
scrollAugInvSel,
crNumFreeSlots,
setInvPosFromSS,
module Dodge.Inventory.RBList,
swapInvItems,
scrollAugNextInSection,
swapItemWith,
) where
import Dodge.Equipment
--import Dodge.Wall.Delete
--import Dodge.Item.Location
import Data.Function
import qualified Data.IntSet as IS
import Data.Maybe
import Dodge.Base
import Dodge.Data.SelectionList
import Dodge.Data.World
--import Dodge.Euse
import Dodge.Inventory.CheckSlots
import Dodge.Inventory.Location
import Dodge.Inventory.RBList
import Dodge.Inventory.Swap
import Dodge.SelectionSections
import Geometry
import qualified IntMapHelp as IM
import LensHelp
import ListHelp
import NewInt
-- TODO check what happens to selection index when dropping non-selected items
-- should consider never fully destroying items, but assigning a flag saying how
-- they were moved from play
destroyInvItem ::
Int ->
-- | Inventory position
Int ->
World ->
World
destroyInvItem cid invid w =
rmInvItem cid invid w & removeitloc
& removeithotkey
where
removeitloc = fromMaybe id $ do
itid <- w ^? cWorld . lWorld . creatures . ix cid . crInv . ix invid . itID . unNInt
return $ cWorld . lWorld . itemLocations . at itid .~ Nothing
removeithotkey = fromMaybe id $ do
itid <- w ^? cWorld . lWorld . creatures . ix cid . crInv . ix invid . itID . unNInt
hk <- w ^? cWorld . lWorld . imHotkeys . unNIntMap . ix itid
return $
(cWorld . lWorld . imHotkeys . unNIntMap . at itid .~ Nothing)
. (cWorld . lWorld . hotkeys . at hk .~ Nothing)
-- | after this the item at the inventory position will no longer exist
rmInvItem ::
-- | Creature id
Int ->
-- | Inventory position
Int ->
World ->
World
rmInvItem cid invid w =
w
& dounequipfunction --the ordering of these is
& pointcid . crInv %~ f -- important
& removeAnySlotEquipment
& pointcid . crEquipment . each %~ g
& updateselection
& updateselectionextra
& pointcid %~ updateRootItemID
& worldEventFlags . at InventoryChange ?~ ()
where
pointcid = cWorld . lWorld . creatures . ix cid
updateselectionextra
| cid == 0 = hud . hudElement . diSelection . _Just . _3 %~ const mempty
| otherwise = id
updateselection
| cid == 0 && cr ^? crManipulation . manObject . imSelectedItem == Just invid =
scrollAugInvSel (-1) . scrollAugInvSel 1
| otherwise =
pointcid . crManipulation . manObject . imSelectedItem %~ g
cr = w ^?! cWorld . lWorld . creatures . ix cid
itm = _crInv cr IM.! invid
dounequipfunction = effectOnRemove itm cr
-- fromMaybe id $ do
-- rmf <- itm ^? itUse . uequipEffect . eeOnRemove
-- return $ doItmCrWdWd rmf itm cr
removeAnySlotEquipment = fromMaybe id $ do
epos <-
w
^? cWorld . lWorld . creatures . ix cid . crInv . ix invid
. itLocation
. ilEquipSite
. _Just
return $ pointcid . crEquipment . at epos .~ Nothing
maxk = fmap fst $ IM.lookupMax $ cr ^. crInv
f inv =
let (xs, ys) = IM.split invid inv
in xs `IM.union` IM.mapKeysMonotonic (subtract 1) ys
-- the following might not work if a non-player creature drops their last item
g x
| x > invid || Just x == maxk = max 0 $ x - 1
| otherwise = x
-- this looks ugly...
updateCloseObjects :: World -> World
updateCloseObjects w =
w
& hud . closeItems %~ f
& hud . closeButtons %~ g
where
g oldbts = intersect oldbts cbts `union` cbts
f olditems = intersect olditems citems `union` citems
cbts = _btID <$> filter (isclose . _btPos) activeButtons
citems =
fmap _flItID
. filter (isclose . _flItPos)
. IM.elems
$ w ^. cWorld . lWorld . floorItems . unNIntMap
isclose pos = dist ypos pos < 40 && hasButtonLOS ypos pos w
ypos = _crPos $ you w
activeButtons =
filter ((/=) BtInactive . _btState)
. IM.elems
$ w ^. cWorld . lWorld . buttons
changeSwapSel :: Int -> World -> World
changeSwapSel yi w
| yi >= 0 = foldl' (&) w $ replicate yi (changeSwapWith $ f IM.cycleLT)
| otherwise = foldl' (&) w $ replicate (negate yi) (changeSwapWith $ f IM.cycleGT)
where
f g i m = fst <$> g i m
changeSwapOther ::
((Int -> Identity Int) -> ManipulatedObject -> Identity ManipulatedObject) ->
Int ->
(Int -> IM.IntMap (SelectionItem ()) -> Maybe Int) ->
Int ->
World ->
World
changeSwapOther manlens n f i w = fromMaybe w $ do
ss <- w ^? hud . hudElement . diSections . ix n . ssItems
k <- f i ss
let doswap j
| j == i = k
| j == k = i
| otherwise = j
return $
w
& swapAnyExtraSelection i k
& cWorld . lWorld . creatures . ix 0 . crManipulation . manObject . manlens
%~ doswap
& hud . closeItems %~ swapIndices i k
& hud . hudElement . diSelection . _Just . _2 %~ doswap
& worldEventFlags . at InventoryChange ?~ ()
swapItemWith ::
(Int -> IM.IntMap (SelectionItem ()) -> Maybe Int) ->
(Int, Int) ->
World ->
World
swapItemWith f (j, i) w = case j of
0 -> w & swapInvItems f i
3 -> w & changeSwapOther ispCloseItem 3 f i
5 -> w & changeSwapOther ispCloseButton 5 f i
_ -> w
changeSwapWith :: (Int -> IM.IntMap (SelectionItem ()) -> Maybe Int) -> World -> World
changeSwapWith f w = case w ^? hud . hudElement . diSelection . _Just of
Just (0, i, _) -> w & swapInvItems f i
Just (3, i, _) -> w & changeSwapOther ispCloseItem 3 f i
Just (5, i, _) -> w & changeSwapOther ispCloseButton 5 f i
_ -> w
invSetSelection :: (Int, Int, IS.IntSet) -> World -> World
invSetSelection sel w =
w
& hud . hudElement . diSelection ?~ sel
& worldEventFlags . at InventoryChange ?~ ()
& setInvPosFromSS
& cWorld . lWorld %~ crUpdateItemLocations 0
invSetSelectionPos :: Int -> Int -> World -> World
invSetSelectionPos i j w =
w
& hud . hudElement . diSelection %~ f
& worldEventFlags . at InventoryChange ?~ ()
& setInvPosFromSS
& cWorld . lWorld %~ crUpdateItemLocations 0
where
f Nothing = Just (i,j,mempty)
f (Just (_,_,s)) = Just (i,j,s)
scrollAugInvSel :: Int -> World -> World
scrollAugInvSel yi w
| yi == 0 = w
| otherwise =
w & hud . hudElement %~ doscroll
& worldEventFlags . at InventoryChange ?~ ()
& setInvPosFromSS
& cWorld . lWorld %~ crUpdateItemLocations 0
where
doscroll he = fromMaybe he $ do
sss <- he ^? diSections
return $ he & diSelection %~ scrollSelectionSections yi sss
scrollAugNextInSection :: World -> World
scrollAugNextInSection w =
w & hud . hudElement %~ doscroll
& worldEventFlags . at InventoryChange ?~ ()
& setInvPosFromSS
& cWorld . lWorld %~ crUpdateItemLocations 0
where
doscroll he = fromMaybe he $ do
sss <- he ^? diSections
return $ he & diSelection %~ nextInSectionSS sss