Files
loop/src/Dodge/Render/HUD.hs
T
2023-05-12 00:48:07 +01:00

357 lines
14 KiB
Haskell

--{-# LANGUAGE TupleSections #-}
module Dodge.Render.HUD (
drawHUD,
) where
import Dodge.Item.Display
import Control.Lens
import Control.Monad
import qualified Data.Map.Strict as M
import Data.Maybe
import qualified Data.Vector as V
import Dodge.Base
import Dodge.Clock
import Dodge.Creature.Info
import Dodge.Data.CardinalPoint
import Dodge.Data.Combine
import Dodge.Data.Config
import Dodge.Data.SelectionList
import Dodge.Data.World
import Dodge.Default.SelectionList
import Dodge.Equipment.Text
import Dodge.Inventory
import Dodge.Item.Info
import Dodge.ListDisplayParams
import Dodge.Render.Connectors
import Dodge.Render.HUD.Carte
import Dodge.Render.List
import Dodge.ScreenPos
import Dodge.SelectionSections
import Dodge.SelectionSections.Draw
import Dodge.Tweak.Show
import Geometry
import qualified IntMapHelp as IM
import Justify
import ListHelp
import Padding
import Picture
import SDL (MouseButton (..))
drawHUD :: Configuration -> World -> Picture
drawHUD cfig w = case w ^. hud . hudElement of
DisplayCarte -> drawCarte cfig w
DisplayInventory{_diSections = sections, _subInventory = subinv} ->
drawHP cfig w
<> drawInventory sections w cfig
<> drawSubInventory subinv cfig w
drawHP :: Configuration -> World -> Picture
drawHP cfig =
dShadCol white
. translate (halfWidth cfig) (halfHeight cfig - 40)
. scale 0.2 0.2
. textRight
. show
. (^?! cWorld . lWorld . creatures . ix 0 . crHP)
drawInventory :: SelectionSections () -> World -> Configuration -> Picture
drawInventory sss = drawSelectionSections sss . invDisplayParams
drawSubInventory :: SubInventory -> Configuration -> World -> Picture
drawSubInventory subinv cfig w = case subinv of
LockedInventory -> mempty -- topInvCursor col cursPos cfig w
NoSubInventory -> drawRBOptions cfig w
ExamineInventory mtweaki -> drawExamineInventory cfig mtweaki w
DisplayTerminal tid -> displayTerminal tid cfig (w ^. cWorld . lWorld)
CombineInventory{_ciSections = sss} -> drawCombineInventory cfig sss w
drawCombineInventory :: Configuration -> SelectionSections CombinableItem -> World -> Picture
drawCombineInventory cfig sss w =
invHead cfig "COMBINE"
<> drawSelectionSections sss secondColumnParams cfig
<> combineInventoryExtra sss cfig w
drawExamineInventory :: Configuration -> Maybe Int -> World -> Picture
drawExamineInventory cfig mtweaki w =
invHead cfig "EXAMINE"
<> examineInventoryExtra mtweaki itm cfig
<> drawSelectionList
secondColumnParams
cfig
( defaultSelectionList & slItems .~ ammoTweakSelectionItems itm
++ map
f
( makeParagraph 60 $
yourAugmentedItem
itemInfo
(yourInfo (you w))
(closeObjectInfo (crNumFreeSlots (you w)))
w
)
)
where
itm = yourItem w
f str =
SelectionItem
{ _siPictures = [str]
, _siHeight = 1
, _siIsSelectable = True
, _siColor = white
, _siOffX = 0
, _siPayload = ()
}
closeObjectInfo :: Int -> Either FloorItem Button -> String
closeObjectInfo n x = case x of
Left FlIt{_flIt = itm} -> itemInfo itm ++ " It is on the floor" ++ floorItemPickupInfo n itm
Right _ -> "Some sort of switch or button."
floorItemPickupInfo :: Int -> Item -> String
floorItemPickupInfo n itm
| n >= ceiling (_itInvSize itm) = ", but you have space to pick it up."
| otherwise = ", and you don't have space to pick it up."
-- note the use of ^?!
-- it is probably desirable for this to crash hard for now
yourAugmentedItem :: (Item -> a) -> a -> (Either FloorItem Button -> a) -> World -> a
yourAugmentedItem f x g w = case you w ^? crManipulation . manObject of
Just (InInventory (SelItem i _)) -> f $ yourInv w ^?! ix i
Just (InNearby (SelCloseObject i)) -> g $ w ^?! hud . closeObjects . ix i
_ -> x
drawRBOptions :: Configuration -> World -> Picture
drawRBOptions cfig w = fromMaybe mempty $ do
guard $ ButtonRight `M.member` _mouseButtons (_input w)
es <- w ^? rbOptions . opEquip
i <- w ^? rbOptions . opSel
ae <- w ^? rbOptions . opAllocateEquipment
sss <- w ^? hud . hudElement . diSections
(i', j) <- sss ^? sssExtra . sssSelPos . _Just
curpos <- selSecSelPos i' j sss
let ytext = drawListElement 0 1 curpos . text
midstr = case ae of
DoNotMoveEquipment -> ""
PutOnEquipment{} -> " PUT ON"
MoveEquipment{} -> " MOVE TO"
SwapEquipment{} -> " MOVE TO"
ReplaceEquipment{} -> " PUT ON"
RemoveEquipment{} -> "TAKE OFF"
extrastr = case ae of
SwapEquipment{_allocOldPos = oldp, _allocSwapID = sid} ->
"SWAPS " ++ otheritem sid ++ " ONTO " ++ eqPosText oldp
ReplaceEquipment{_allocRemoveID = rid} ->
"REMOVES " ++ otheritem rid
_ -> ""
return $
toTopLeft cfig
$ translate 290 (-1) (ytext midstr)
<> translate 160 (-1) (listCursorChooseBorderScale 0 1 [North,South] curpos 0 white 21 1)
<> translate 380 (-1) (drawListYoff (curpos - i) (map (text . eqPosText) es))
<> translate 380 (-1) (listCursorChooseBorderScale 0 1 [East] (curpos - i) 0 white 7 (length es))
<> translate 380 (-1) (listCursorChooseBorderScale 0 1 [West] (curpos + 1) 0 white 7 (length es - (i+1)))
<> translate 380 (-1) (listCursorChooseBorderScale 0 1 [West] (curpos - i) 0 white 7 i)
<> translate 380 (-1) (maybetopborder i curpos)
<> translate 380 (-1) (maybebottomborder i (length es) curpos)
<> translate 460 (-1) (ytext extrastr)
where
maybetopborder 0 curpos= listCursorChooseBorderScale 0 1 [North] curpos 0 white 7 1
maybetopborder _ _ = mempty
maybebottomborder a b curpos
| a == b - 1
= listCursorChooseBorderScale 0 1 [South] curpos 0 white 7 1
| otherwise = mempty
otheritem j = fromMaybe "" $ do
itm <- you w ^? crInv . ix j
return $ itemBaseName itm
examineInventoryExtra :: Maybe Int -> Maybe Item -> Configuration -> Picture
examineInventoryExtra mtweaki mitm cfig = fromMaybe mempty $ do
tweaki <- mtweaki
-- consider moving this functionality out into a tweaks module
tparam <- mitm ^? _Just . itTweaks . tweakParams . ix tweaki
return $
toTopLeft cfig $
translate subInvX (-60) $
listCursorNSW tweaki 0 white (length $ showTweak tparam) 15
combineInventoryExtra :: SelectionSections CombinableItem -> Configuration -> World -> Picture
combineInventoryExtra sss cfig w = fromMaybe mempty $ do
(i, j) <- sss ^? sssExtra . sssSelPos . _Just
si <- sss ^? sssSections . ix i . ssItems . ix j
cpos <- selSecSelPos i j sss
let col = _siColor si
return $
mconcat
[ fromMaybe mempty $ do
strs <- si ^? siPayload . ciInfo
return $ toTopLeft cfig (translate (subInvX + 150) 60 $ drawListYoff cpos $ map (color red . text) strs)
, fromMaybe mempty $ do
lnks <- si ^? siPayload . ciInvIDs
return $
lnkMidPosInvSelsCol cfig w cpos col lnks
<> foldMap invcursor lnks
<> combineCounts cfig w lnks
]
where
invcursor i = fromMaybe mempty $ do
sss' <- w ^? hud . hudElement . diSections
let idp = invDisplayParams w
return $
translateScreenPos cfig (idp ^. ldpPos) $
selSecDrawCursor 17 [North, South, East] idp sss' 0 i
displayTerminal :: Int -> Configuration -> LWorld -> Picture
displayTerminal tid cfig w = fromMaybe mempty $ do
tm <- w ^? terminals . ix tid
return $
invHead cfig (_tmTitle tm ++ ":T" ++ show tid)
<> drawSelectionList secondColumnParams cfig (thesellist tm)
where
toselitm (str, col) = SelectionItem [str] 1 True col 0 ()
thesellist tm = defaultSelectionList & slItems .~ thelist tm
thelist tm =
map toselitm . displayTermInput tm
. reverse
. take (_tmMaxLines tm)
$ _tmDisplayedLines tm
displayTermInput tm = case _tmInput tm of
TerminalInput{_tiText = s, _tiFocus = hasfoc} ->
(++ [(displayInputText tm s ++ displayBlinkCursor hasfoc, white)])
partcommand tm = maybe "" (++ " ") $ tm ^? tmPartialCommand . _Just . tcString
displayInputText tm s
| _tmStatus tm == TerminalReady = partcommand tm ++ "> " ++ s
| otherwise = ""
displayBlinkCursor hasfoc
| hasfoc = clockCycle 10 (V.fromList ["_", "."]) w
| otherwise = []
combineCounts :: Configuration -> World -> [Int] -> Picture
combineCounts cfig w = foldMap f . group
where
f (i : is) = fromMaybe mempty $ do
_ <- yourInv w ^? ix i . itUse . useAmount
sss <- w ^? hud . hudElement . diSections
p <- selNumTextEndPos cfig (invDisplayParams w) sss 0 i
col <- selSecSelCol 0 i sss
return $ color col $ uncurryV translate p . scale 0.1 0.1 . text $ ('-' : show (length is + 1))
f _ = mempty
lnkMidPosInvSelsCol :: Configuration -> World -> Int -> Color -> [Int] -> Picture
lnkMidPosInvSelsCol cfig w i col = foldMap f
where
f j = fromMaybe mempty $ do
sss <- w ^? hud . hudElement . diSections
h <- selNumEndMidHeight cfig (invDisplayParams w) sss 0 j
invcol <- selSecSelCol 0 j sss
return $ zConnectCol rp (V2 18 0 + h) col white white invcol
rp = V2 (190 - hw) (hh - (20 * fromIntegral i + 77.5))
hh = halfHeight cfig
hw = halfWidth cfig
ammoTweakSelectionItems :: Maybe Item -> [SelectionItem ()]
ammoTweakSelectionItems = textSelItems . ammoTweakStrings
ammoTweakStrings :: Maybe Item -> [String]
ammoTweakStrings it = case it ^? _Just . itTweaks . tweakParams of
Just l -> map tweakString $ IM.elems l
_ -> ["NOT TWEAKABLE"]
tweakString :: TweakParam -> String
tweakString tp = rightPad 12 ' ' (show $ _tweakType tp) ++ " " ++ showTweak tp
invHead :: Configuration -> String -> Picture
invHead cfig =
translateScreenPos cfig (fromTopLeft (V2 subInvX 80))
. dShadCol white
. scale 0.4 0.4
. textJustifyLeft
--locPoss = map (cartePosToScreen cfig (w ^. hud) . ($ w) . doWorldPos . fst) . IM.elems . _seenLocations . _lWorld $ _cWorld w
--locTexts = map fst locs
--displayListEndCoords :: Configuration -> [String] -> [Point2]
--displayListEndCoords cfig ss = map (doWindowScale cfig) $ zipWith h ss $ map f [1 ..]
-- where
-- f :: Int -> Point2
-- f i = V2 (15 - halfWidth cfig) (2.5 + halfHeight cfig - (20 * fromIntegral i))
-- h :: String -> Point2 -> Point2
-- h s (V2 x y) = V2 (x + 9 * fromIntegral (length s)) y
--selectedCloseObjectLink :: Configuration -> World -> Picture
--selectedCloseObjectLink cfig w = mempty
-- | Pictures of popup text for items close to your position.
--closeObjectTexts :: Configuration -> World -> Picture
--closeObjectTexts cfig w = pictures $
-- renderListAt pushout (negate 20 * fromIntegral invPos) cfig (map colAndText $ _closeObjects w)
-- : maybeToList maybeLine
-- where
-- colAndText (Left x) = ( _itName $ _flIt x, _itInvColor $ _flIt x)
-- colAndText (Right x) = (_btText x,yellow)
-- youSel = _crInvSel $ you w
-- freeSlot = mayIt >>= \it -> checkInvSlotsYou (_flIt it) w
-- invPos = fromMaybe youSel freeSlot
-- mayObj = listToMaybe $ _closeObjects w
-- mayIt = mayObj >>= maybeLeft
-- maybeLeft (Left x) = Just x
-- maybeLeft _ = Nothing
-- pushout = 120
-- objPos obj = case obj of
-- Left flit -> _flItPos flit
-- Right bt -> _btPos bt
-- mayScreenPos = fmap (worldPosToScreen w . objPos) mayObj
-- maybeLine = do
-- itScreenPos <- mayScreenPos
-- (theText,col) <- fmap colAndText mayObj
-- let textWidth = 9 * fromIntegral (length theText)
-- let p = V2 (textWidth + 15 + pushout - halfWidth cfig)
-- ( halfHeight cfig - 20* (fromIntegral invPos +1) + 2.5)
-- return . winScale cfig . color col $ lConnect p itScreenPos
textSelItems :: [String] -> [SelectionItem ()]
textSelItems = map (picsToSelectable . (: []))
picsToSelectable :: [String] -> SelectionItem ()
picsToSelectable pics =
SelectionItem
{ _siPictures = pics
, _siHeight = length pics
, _siIsSelectable = True
, _siColor = white
, _siOffX = 0
, _siPayload = ()
}
-- 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