module Dodge.Inventory.Location (updateRootItemID , crUpdateItemLocations , setInvPosFromSS -- , tryGetRootItemInvID ) where import NewInt import qualified Data.IntSet as IS import Dodge.Base.You import Dodge.Data.SelectionList import Dodge.Data.Item.Use.Consumption.LoadAction import Control.Lens import Dodge.Data.World import qualified IntMapHelp as IM import Dodge.Item.Grammar import Data.Maybe import Control.Applicative -- assumes all item locations inside the items are correct tryGetRootAttachedFromInvID :: Int -> IM.IntMap Item -> Maybe (Int, IS.IntSet) tryGetRootAttachedFromInvID invid im = do let imroots = invRootMap im theroot = fromMaybe invid $ imroots ^? ix invid . _1 . _Just t <- imroots ^? ix theroot . _2 --return (theroot, foldMap (IS.singleton . (^?! _1 . itLocation . ilInvID)) t) return (theroot, foldMap (IS.singleton . (^?! itLocation . ilInvID)) t) -- this assumes the creature inventory is well formed, specifically the -- location ids tryGetRootItemInvID :: Int -> Creature -> Maybe Int tryGetRootItemInvID i cr = do let adj = case invAdj (_crInv cr) of Left str -> error $ "tryToGetRootItemInvID: "++ str Right x -> x theroot <- adj ^? ix i theroot ^? _1 . _Just . _1 <|> Just i updateRootItemID :: Creature -> Creature updateRootItemID cr = fromMaybe cr $ do i <- cr ^? crManipulation . manObject . imSelectedItem j <- tryGetRootItemInvID i cr return $ cr & crManipulation . manObject . imRootItem .~ j -- the following assumes that the crManipulation is correct crUpdateItemLocations :: Int -> LWorld -> LWorld crUpdateItemLocations crid lw = fromMaybe lw $ do mo <- lw ^? creatures . ix crid . crManipulation . manObject crinv <- lw ^? creatures . ix crid . crInv return $ IM.foldlWithKey' (crUpdateInvidLocations mo crid) lw crinv crUpdateInvidLocations :: ManipulatedObject -> Int -> LWorld -> Int -> Item -> LWorld crUpdateInvidLocations mo crid lw invid itm = lw & creatures . ix crid . crInv . ix invid . itLocation .~ newloc & itemLocations %~ IM.insert itid newloc where itid = itm ^. itID . unNInt newloc = InInv { _ilCrID = crid , _ilInvID = invid , _ilIsRoot = Just invid == mo ^? imRootItem , _ilIsSelected = Just invid == mo ^? imSelectedItem , _ilIsAttached = invid `IS.member` (mo ^. imAttachedItems) } -- this should be looked at, as it is sometimes used in functions that need not -- concern the player creature -- this might not work if the selpos is in the inventory but too large setInvPosFromSS :: World -> World setInvPosFromSS w = w & cWorld . lWorld . creatures . ix 0 . crManipulation . manObject .~ thesel where thesel = fromMaybe SelNothing $ do sss <- w ^? hud . hudElement . diSections (i, j) <- sss ^? sssExtra . sssSelPos . _Just case i of (-1) -> Just SortInventory 0 -> do (rootid,aset) <- tryGetRootAttachedFromInvID j (you w ^. crInv) return SelectedItem { _imSelectedItem = j , _imRootItem = rootid , _imAttachedItems = aset } 1 -> Just SelNothing 2 -> Just SortNearby 3 -> Just $ SelCloseObject j _ -> error "selection out of bounds"