{-# LANGUAGE TupleSections #-} module Dodge.Inventory ( selSecSelPos, checkInvSlotsYou, rmSelectedInvItem, selNumPos, selNumTextEndPos, selSecSelCol, selNumEndMidHeight, rmInvItem, updateCloseObjects, updateRBList, updateTerminal, closeObjScrollDir, changeSwapInvSel, scrollAugInvSel, crNumFreeSlots, crInvSize, selectedCloseObject, invDimColor, setInvPosFromSS, ) where import Dodge.SelectionSections import Control.Applicative import Dodge.Data.SelectionList import Color import qualified Data.Map.Strict as M import Data.Maybe import Dodge.Base import Dodge.Data.Config import Dodge.Data.World import Dodge.Euse import Dodge.Inventory.CheckSlots import Dodge.Inventory.CloseObject import Dodge.Inventory.Color import Dodge.ItEffect import Dodge.Reloading import Geometry import qualified IntMapHelp as IM import LensHelp import ListHelp import Padding -- | 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 = case w ^? getcid . crInv . ix invid . itUse . useAmount of Just x | x > 1 -> w & pointcid . crInv . ix invid . itUse . useAmount -~ 1 _ -> w & pointcid . crInv %~ f & pointcid %~ crCancelReloading & pointcid . crLeftInvSel . lisMPos %~ g' & removeAnySlotEquipment & dounequipfunction & doanyitemeffect & pointcid . crInvEquipped %~ IM.delete invid & pointcid . crInvEquipped %~ IM.mapKeys g & updateselection where getcid = cWorld . lWorld . creatures . ix cid pointcid = cWorld . lWorld . creatures . ix cid updateselection | cid == 0 && cr ^? crManipulation . manObject . inInventory . ispItem == Just invid = scrollAugInvSel (-1) . scrollAugInvSel 1 | otherwise = pointcid . crManipulation . manObject . inInventory . ispItem %~ g cr = w ^?! cWorld . lWorld . creatures . ix cid itm = _crInv cr IM.! invid dounequipfunction = fromMaybe id $ do rmf <- itm ^? itUse . equipEffect . eeOnRemove return $ useE rmf itm cr doanyitemeffect = fromMaybe id $ do rmf <- itm ^? itEffect . ieOnDrop return $ doInvEffect rmf itm cr removeAnySlotEquipment = case w ^? cWorld . lWorld . creatures . ix cid . crInvEquipped . ix invid of Just epos -> pointcid . crEquipment . at epos .~ Nothing Nothing -> id 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 g' Nothing = Nothing g' (Just x) | x == invid = Nothing | x > invid || Just x == maxk = Just $ max 0 $ x - 1 | otherwise = Just x rmSelectedInvItem :: Int -> World -> World rmSelectedInvItem cid w = case w ^? cWorld . lWorld . creatures . ix cid . crManipulation . manObject . inInventory . ispItem of Just i -> rmInvItem cid i w Nothing -> w selNumPos :: ManipulatedObject -> World -> Maybe Int selNumPos mo w = w ^? hud . hudElement . diSections >>= case mo of InInventory SortInventory -> selSecSelPos (-1) 0 InInventory (SelItem i _) -> selSecSelPos 0 i SelNothing -> selSecSelPos 1 0 InNearby SortNearby -> selSecSelPos 2 0 InNearby (SelCloseObject i) -> selSecSelPos 3 i -- there are still more ListDisplayParams to integrate here selNumTextEndPos :: Configuration -> ListDisplayParams -> SelectionSections a -> Int -> Int -> Maybe Point2 selNumTextEndPos cfig ldp sss i j = do ipos <- selSecSelPos i j sss return $ V2 (150 - hw) (hh - ((s * 10 + ygap) * (fromIntegral ipos + 1))) where s = _ldpScale ldp ygap = _ldpVerticalGap ldp hh = halfHeight cfig hw = halfWidth cfig selNumEndMidHeight :: Configuration -> ListDisplayParams -> SelectionSections a -> Int -> Int -> Maybe Point2 selNumEndMidHeight cfig ldp sss i j = do ipos <- selSecSelPos i j sss size <- selSecSelSize i j sss --let bump = negate $ (10 * s + ygap) * fromIntegral size return $ V2 (150 - hw) (hh - ((10 * s + ygap) * (fromIntegral ipos + fromIntegral size * 0.5))) where s = _ldpScale ldp ygap = _ldpVerticalGap ldp hh = halfHeight cfig hw = halfWidth cfig selSecSelCol :: Int -> Int -> SelectionSections a -> Maybe Color selSecSelCol i j sss = sss ^? sssSections . ix i . ssItems . ix j . siColor updateTerminal :: World -> World updateTerminal = checkTermDist checkTermDist :: World -> World checkTermDist w = case w ^? hud . hudElement . subInventory . termID of Just tmid -> fromMaybe (w & hud . hudElement . subInventory .~ NoSubInventory) $ do btid <- w ^? cWorld . lWorld . terminals . ix tmid . tmButtonID btpos <- w ^? cWorld . lWorld . buttons . ix btid . btPos if dist btpos (_crPos $ you w) < 40 then Just w else Nothing Nothing -> w -- this looks ugly... updateCloseObjects :: World -> World updateCloseObjects w = w & hud . closeObjects .~ newcloseobjects & updatecursorposifnecessary where newcloseobjects = unionBy closeObjEq oldCloseFiltered currentClose updatecursorposifnecessary = case w ^? cWorld . lWorld . creatures . ix 0 . crManipulation . manObject. inNearby . ispCloseObject of Just i | i >= length newcloseobjects -> scrollAugInvSel 1 | isNothing (w ^? hud . hudElement . diSections . sssSections . ix 3 . ssItems . ix i) -> scrollAugInvSel (-1) _ -> id 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 $ w ^. cWorld . lWorld . buttons currentClose = filt $ map Left (IM.elems $ w ^. cWorld . lWorld . floorItems) ++ activeButtons oldClose = filt $ mapMaybe updatebyid $ w ^. hud . closeObjects oldCloseFiltered = intersectBy closeObjEq oldClose currentClose updatebyid (Left flid) = fmap Left $ w ^? cWorld . lWorld . floorItems . ix (_flItID flid) updatebyid (Right btid) = fmap Right $ w ^? cWorld . lWorld . buttons . ix (_btID btid) updateRBList :: World -> World updateRBList w | w ^? rbOptions . opItemID == mcurrentitemid = w & setEquipAllocation & setEquipActivation | otherwise = fromMaybe (w & rbOptions .~ NoRightButtonOptions) $ do i <- cr ^? crManipulation . manObject . inInventory . ispItem esite <- cr ^? crInv . ix i . itUse . equipEffect . eeSite itid <- mcurrentitemid return $ w & rbOptions .~ EquipOptions { _opEquip = equipSiteToPositions esite , _opSel = chooseEquipmentPosition cr (equipSiteToPositions esite) , _opItemID = itid , _opAllocateEquipment = DoNotMoveEquipment , _opActivateEquipment = NoChangeActivateEquipment } & setEquipAllocation & setEquipActivation where mcurrentitemid = do i <- cr ^? crManipulation . manObject . inInventory . ispItem cr ^? crInv . ix i . itID --curinvid = crSel cr cr = you w chooseEquipmentPosition :: Creature -> [EquipPosition] -> Int chooseEquipmentPosition cr eps = fromMaybe (chooseFreeSite cr eps) $ do i <- cr ^? crManipulation . manObject . inInventory . ispItem ep <- cr ^? crInvEquipped . ix i elemIndex ep eps chooseFreeSite :: Creature -> [EquipPosition] -> Int chooseFreeSite cr = fromMaybe 0 . findIndex hasnoequipment where hasnoequipment ep = isNothing $ cr ^? crEquipment . ix ep setEquipAllocation :: World -> World setEquipAllocation w = fromMaybe w $ do curpos <- you w ^? crManipulation . manObject . inInventory . ispItem return $ case _rbOptions w of EquipOptions{_opEquip = es, _opSel = i} -> case you w ^? crInvEquipped . ix curpos of Just epos | es !! i == epos -> w & rbOptions . opAllocateEquipment .~ RemoveEquipment { _allocOldPos = epos } Just epos | isJust (you w ^? crEquipment . ix (es !! i)) -> w & rbOptions . opAllocateEquipment .~ SwapEquipment { _allocOldPos = epos , _allocNewPos = es !! i , _allocSwapID = _crEquipment (you w) M.! (es !! i) } Just epos -> w & rbOptions . opAllocateEquipment .~ MoveEquipment { _allocOldPos = epos , _allocNewPos = es !! i } Nothing | isJust (you w ^? crEquipment . ix (es !! i)) -> w & rbOptions . opAllocateEquipment .~ ReplaceEquipment { _allocNewPos = es !! i , _allocRemoveID = _crEquipment (you w) M.! (es !! i) } Nothing -> w & rbOptions . opAllocateEquipment .~ PutOnEquipment { _allocNewPos = es !! i } _ -> w setEquipActivation :: World -> World setEquipActivation w = case w ^? rbOptions . opAllocateEquipment of Just DoNotMoveEquipment -> w Just RemoveEquipment{} -> case you w ^. crLeftInvSel . lisMPos of Just i | Just i == minvsel -> w & rbOptions . opActivateEquipment .~ DeactivateEquipment { _deactivateEquipment = i } _ -> w & rbOptions . opActivateEquipment .~ NoChangeActivateEquipment Just rbos -> case you w ^. crLeftInvSel . lisMPos of Just i | Just i == minvsel -> w & rbOptions . opActivateEquipment .~ NoChangeActivateEquipment Just i | invselcanactivate -> w & rbOptions . opActivateEquipment .~ ActivateDeactivateEquipment { _activateEquipment = fromJust minvsel , _deactivateEquipment = i } Just i | Just i == rbos ^? allocRemoveID -> w & rbOptions . opActivateEquipment .~ DeactivateEquipment i Just _ -> w & rbOptions . opActivateEquipment .~ NoChangeActivateEquipment Nothing | invselcanactivate -> w & rbOptions . opActivateEquipment .~ ActivateEquipment { _activateEquipment = fromJust minvsel } Nothing -> w & rbOptions . opActivateEquipment .~ NoChangeActivateEquipment Nothing -> w & rbOptions . opActivateEquipment .~ NoChangeActivateEquipment where --invsel = crSel (you w) minvsel = cr ^? crManipulation . manObject . inInventory . ispItem cr = you w invselcanactivate = isJust $ do i <- minvsel return $ cr ^? crInv . ix i . itUse . leftUse equipSiteToPositions :: EquipSite -> [EquipPosition] equipSiteToPositions es = case es of GoesOnHead -> [OnHead] GoesOnChest -> [OnChest] GoesOnBack -> [OnBack] GoesOnWrist -> [OnLeftWrist, OnRightWrist] GoesOnLegs -> [OnLegs] closeObjScrollDir :: Float -> World -> World closeObjScrollDir x | x > 0 = over (hud . closeObjects) rotU | x < 0 = over (hud . closeObjects) rotD | otherwise = id changeSwapInvSel :: Int -> World -> World changeSwapInvSel k w = case you w ^? crManipulation . manObject of Just (InInventory (SelItem i _)) -> w & cWorld . lWorld . creatures . ix 0 %~ updatecreature i Just (InNearby (SelCloseObject i)) -> w & cWorld . lWorld . creatures . ix 0 . crManipulation . manObject . inNearby . ispCloseObject .~ ((i - k) `mod` numCO) & hud . closeObjects %~ swapIndices i ((i - k) `mod` numCO) _ -> w where updatecreature i = (crInv %~ IM.safeSwapKeys (i `mod` n) (swapi i)) . (crLeftInvSel . lisMPos . _Just %~ updateLeftInvSel i) . (crManipulation . manObject . inInventory . ispItem %~ (`mod` n) . subtract k) . (crInvEquipped %~ IM.safeSwapKeys i (swapi i)) . swapSite i (swapi i) . swapSite (swapi i) i swapSite a b = case cr ^? crInvEquipped . ix a of Just epos -> crEquipment . ix epos .~ b Nothing -> id cr = you w swapi i = (i - k) `mod` n updateLeftInvSel i li | i == li = swapi i | swapi i == li = i | otherwise = li n = length $ _crInv cr numCO = length $ w ^. hud . closeObjects scrollAugInvSel :: Int -> World -> World scrollAugInvSel yi w | yi == 0 = w | otherwise = w & hud . hudElement . diSections %~ scrollSelectionSections yi & setInvPosFromSS 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 ^? sssSelPos . _Just -- j <- sss ^? sssSections . ix i . ssCursor . _Just . scurSel case i of (-1) -> Just $ InInventory SortInventory 0 -> Just $ InInventory (SelItem j NoInvSelAction) 1 -> Just SelNothing 2 -> Just $ InNearby SortNearby 3 -> Just $ InNearby $ SelCloseObject j _ -> error "selection out of bounds" selectedCloseObject :: World -> Maybe (Either FloorItem Button) selectedCloseObject w = do i <- you w ^? crManipulation . manObject . inNearby . ispCloseObject <|> fmap fst (IM.lookupMin =<< w ^? hud . hudElement . diSections . sssSections . ix 3 . ssItems) w ^? hud . closeObjects . ix i