111 lines
4.0 KiB
Haskell
111 lines
4.0 KiB
Haskell
{-# LANGUAGE LambdaCase #-}
|
|
|
|
module Dodge.Door (updateDoor) where
|
|
|
|
import Data.Foldable
|
|
import Data.Maybe
|
|
import qualified Data.Set as S
|
|
import Dodge.Data.World
|
|
import Dodge.Door.DoorLerp
|
|
import Dodge.ShiftPoint
|
|
import Dodge.SoundLogic
|
|
import Dodge.Wall.Move
|
|
import Dodge.WorldBool
|
|
import Dodge.Zoning.Base
|
|
import Dodge.Zoning.Pathing
|
|
import Geometry.Data
|
|
import LensHelp
|
|
import Linear
|
|
import Picture.Data
|
|
import Shape.Data
|
|
|
|
updateDoor :: Door -> World -> (S.Set Int2, World)
|
|
updateDoor dr w = case dr ^. drUpdate of
|
|
DoorLerp x -> doorLerp x dr w
|
|
DoorLerpWithTimer n x -> doorLerpWithTimer n x dr w
|
|
DoorDoNothing ->
|
|
( mempty
|
|
, foldl' (doDoorMount (doDoorLerp dr (dr ^. drLerp))) w (dr ^. drMounts)
|
|
)
|
|
|
|
-- could filter these HERE rather than later?
|
|
doDoorMount :: Point2A -> World -> MountedObject -> World
|
|
doDoorMount pa w = \case
|
|
MountedLight p r c ->
|
|
w & cWorld . lWorld . lights .:~ LSParam (p & _xy %~ shiftPointBy pa) r c
|
|
MountedSPic x ->
|
|
w & cWorld . lWorld . tempSPic
|
|
<>~ ( x & _1 . each . sfVs . each . _xy %~ shiftPointBy pa
|
|
& _2 . each . vxPos . _xy %~ shiftPointBy pa
|
|
)
|
|
|
|
-- do the mounts need to be done if there is no lerping?
|
|
doorLerp :: Float -> Door -> World -> (S.Set Int2, World)
|
|
doorLerp speed dr w = fromMaybe (mempty, domounts (dr ^. drLerp) $ setOldLerp w) $ do
|
|
x <- newlerp
|
|
let ps = wlposs x
|
|
ps' = wlposs (dr ^. drLerp)
|
|
is = foldMap (S.fromList . uncurry (zoneOfSeg peZoneSize)) (ps <> ps')
|
|
-- it seems possible that this will miss some paths: we don't add zones for the
|
|
-- old footprint. Seems unlikely, but a possible cause of pathfinding bugs
|
|
return
|
|
( is
|
|
, domounts x $
|
|
f x
|
|
& playSound x
|
|
& cWorld . lWorld . doors . ix drid . drLerp .~ x
|
|
& setOldLerp
|
|
)
|
|
where
|
|
setOldLerp = cWorld . lWorld . doors . ix drid . drOldLerp .~ (dr ^. drLerp)
|
|
domounts x w' = foldl' (doDoorMount (doDoorLerp dr x)) w' (dr ^. drMounts)
|
|
f = ifoldl' (flip . moveWallID) w . wlposs
|
|
wlposs x = (dr ^. drFootPrint) & each . each %~ shiftPointBy (doDoorLerp dr x)
|
|
clerp = dr ^. drLerp
|
|
newlerp
|
|
| toOpen && clerp < 1 = Just . min 1 $ clerp + speed
|
|
| clerp > 0 && not toOpen = Just . max 0 $ clerp - speed
|
|
| otherwise = Nothing
|
|
toOpen = doWdBl (_drTrigger dr) w
|
|
drid = _drID dr
|
|
playSound x
|
|
| _drPushedBy dr == PushesItself =
|
|
soundContinue (WallSound drid) (fst $ doDoorLerp dr x) slideDoorS (Just 1)
|
|
| otherwise = id
|
|
|
|
doorLerpWithTimer :: Int -> Float -> Door -> World -> (S.Set Int2, World)
|
|
doorLerpWithTimer n speed dr w = fromMaybe (mempty, domounts (dr ^. drLerp) w & uptimer) $ do
|
|
x <- newlerp
|
|
let ps = wlposs x
|
|
ps' = wlposs (dr ^. drLerp)
|
|
is = foldMap (S.fromList . uncurry (zoneOfSeg peZoneSize)) (ps <> ps')
|
|
-- it seems possible that this will miss some paths: we don't add zones for the
|
|
-- old footprint. Seems unlikely, but a possible cause of pathfinding bugs
|
|
return
|
|
( is
|
|
, domounts x $
|
|
f x
|
|
& playSound x
|
|
& cWorld . lWorld . doors . ix drid . drLerp .~ x
|
|
& uptimer
|
|
)
|
|
where
|
|
domounts x w' = foldl' (doDoorMount (doDoorLerp dr x)) w' (dr ^. drMounts)
|
|
f = ifoldl' (flip . moveWallID) w . wlposs
|
|
wlposs x = (dr ^. drFootPrint) & each . each %~ shiftPointBy (doDoorLerp dr x)
|
|
clerp = dr ^. drLerp
|
|
newlerp
|
|
| toOpen && clerp < 1 = Just . min 1 $ clerp + speed
|
|
| clerp > 0 && not toOpen = Just . max 0 $ clerp - speed
|
|
| otherwise = Nothing
|
|
uptimer = cWorld . lWorld . doors . ix drid . drUpdate . drLerpTimer %~ updatetimer
|
|
updatetimer
|
|
| doWdBl (_drTrigger dr) w = const 20
|
|
| otherwise = max 0 . subtract 1
|
|
toOpen = doWdBl (_drTrigger dr) w || n > 0
|
|
drid = _drID dr
|
|
playSound x
|
|
| _drPushedBy dr == PushesItself =
|
|
soundContinue (WallSound drid) (fst $ doDoorLerp dr x) slideDoorS (Just 1)
|
|
| otherwise = id
|