139 lines
5.2 KiB
Haskell
139 lines
5.2 KiB
Haskell
--{-# LANGUAGE BangPatterns #-}
|
|
module Dodge.LevelGen.TriggerDoor
|
|
( putDoor
|
|
, putDoubleDoor
|
|
, putSingleDoor
|
|
, addButtonDoor
|
|
, addSwitchDoor
|
|
) where
|
|
import Dodge.Data
|
|
import Dodge.Base
|
|
import Dodge.Base.Zone
|
|
import Dodge.LevelGen.Switch
|
|
import Dodge.LevelGen.Pathing
|
|
import Dodge.LevelGen.MoveDoor
|
|
import Dodge.LevelGen.DoorPane
|
|
import Picture
|
|
import Geometry
|
|
import qualified DoubleStack as DS
|
|
import qualified IntMapHelp as IM
|
|
|
|
import Data.List
|
|
import Data.Maybe
|
|
import Control.Lens
|
|
import Data.Graph.Inductive hiding ((&))
|
|
|
|
-- probably don't have to rebuild the entire graph, oh well
|
|
addButtonDoor :: Color -> Point2 -> Float -> Point2 -> Point2 -> Float -> World -> World
|
|
addButtonDoor c btp btr a b speed w
|
|
= over buttons (IM.insert bid bt)
|
|
$ set pathPoints (foldr insertPoint IM.empty (labNodes newGraph))
|
|
$ set pathGraph newGraph
|
|
$ set pathGraph' newGraphPairs
|
|
$ putDoubleDoor c cond a b speed w
|
|
where
|
|
bid = IM.newKey $ _buttons w
|
|
cond w' = BtNoLabel == _btState (_buttons w' IM.! bid)
|
|
bt = (makeButton c eff) {_btPos = btp, _btRot = btr, _btID = bid}
|
|
(newGraphPairs,removedPairs) = partition (isNothing . uncurry (intersectSegSeg a b))
|
|
$ _pathGraph' w
|
|
newGraph = pairsToGraph dist newGraphPairs
|
|
insertPoint pp@(_,V2 x y) = insertInZoneWith (floorHun x) (floorHun y) (++) [pp]
|
|
eff w' = over pathGraph' (removedPairs ++)
|
|
. over pathGraph (flip run_ $ insMapEdgesM $ map f removedPairs) $ w'
|
|
f (x,y) = (x,y,dist x y)
|
|
-- this has been repeated at least three times: TO BE UNIFIED, REFACTORED
|
|
addSwitchDoor :: Color -> Point2 -> Float -> Point2 -> Point2 -> Float -> World -> World
|
|
addSwitchDoor c btp btr a b speed w = over buttons (IM.insert bid bt)
|
|
$ set pathPoints (foldr insertPoint IM.empty (labNodes newGraph))
|
|
$ set pathGraph newGraph
|
|
$ set pathGraph' newGraphPairs
|
|
$ putDoubleDoor c cond a b speed w
|
|
where
|
|
bid = IM.newKey $ _buttons w
|
|
cond w' = BtOn == _btState (_buttons w' IM.! bid)
|
|
bt = (makeSwitch c openDoor closeDoor) {_btPos = btp, _btRot = btr, _btID = bid}
|
|
(newGraphPairs,removedPairs) = partition (isNothing . uncurry (intersectSegSeg a b))
|
|
$ _pathGraph' w
|
|
newGraph = pairsToGraph dist newGraphPairs
|
|
insertPoint pp@(_,V2 x y) = insertInZoneWith (floorHun x) (floorHun y) (++) [pp]
|
|
openDoor w' = over pathGraph' (removedPairs ++)
|
|
. over pathGraph (flip run_ $ insMapEdgesM $ map f removedPairs) $ w'
|
|
f (x,y) = (x,y,dist x y)
|
|
closeDoor w' = over pathGraph' (\\ removedPairs)
|
|
. over pathGraph (flip run_ $ delMapEdgesM removedPairs) $ w'
|
|
|
|
putDoor
|
|
:: Color
|
|
-> (World -> Bool) -- ^ Opening condition
|
|
-> [(Point2,Point2)] -- ^ Door positions, closed to open.
|
|
-- Bumped out up and down by 9, not widened
|
|
-> World
|
|
-> World
|
|
putDoor c cond pss = over walls triggerDoor
|
|
where
|
|
triggerDoor wls = IM.union wls $ IM.fromList $ zip is $ mkTriggerDoor c cond pss is
|
|
where
|
|
is = [IM.newKey wls..]
|
|
|
|
putDoubleDoor :: Color -> (World -> Bool) -> Point2 -> Point2 -> Float -> World -> World
|
|
putDoubleDoor c cond a b speed = over walls triggerDoubleDoor
|
|
where
|
|
triggerDoubleDoor wls = IM.union wls $ IM.fromList $ zip is $ mkDoubleDoor c False cond a b speed is
|
|
where
|
|
is = [IM.newKey wls..]
|
|
|
|
putSingleDoor :: Color -> (World -> Bool) -> Point2 -> Point2 -> Float -> World -> World
|
|
putSingleDoor c cond a b speed = over walls putTheDoor
|
|
where
|
|
putTheDoor wls = IM.union wls $ IM.fromList $ zip is $ mkSingleDoor c False cond a b speed is
|
|
where
|
|
is = [IM.newKey wls..]
|
|
|
|
mkTriggerDoor
|
|
:: Color
|
|
-> (World -> Bool) -- ^ Opening condition
|
|
-> [(Point2,Point2)] -- ^ List of wall position pairs, closed to open
|
|
-> [Int] -- ^ Wall ids
|
|
-> [Wall]
|
|
{-# INLINE mkTriggerDoor #-}
|
|
mkTriggerDoor c cond ppairs is = zipWith (triggerDoorPane c cond) is $
|
|
transpose $ map toPanePoints ppairs
|
|
|
|
toPanePoints :: (Point2,Point2) -> [(Point2,Point2)]
|
|
{-# INLINE toPanePoints #-}
|
|
toPanePoints (x,y) =
|
|
[ (y +.+ perp, y -.- perp)
|
|
, (y -.- perp, x -.- perp)
|
|
, (x -.- perp, x +.+ perp)
|
|
, (x +.+ perp, y +.+ perp)
|
|
]
|
|
where
|
|
perp = 9 *.* errorNormalizeV 49 ( vNormal (x -.- y))
|
|
{- |
|
|
Zoning might be an issue here.
|
|
It is necessary in the current version, but I am not sure of its behaviour. -}
|
|
triggerDoorPane
|
|
:: Color
|
|
-> (World -> Bool) -- ^ Opening condition
|
|
-> Int -- ^ Wall id
|
|
-> [(Point2,Point2)] -- ^ List of positions: closed to open
|
|
-> Wall
|
|
triggerDoorPane c cond n poss = Door
|
|
{ _wlLine = head poss
|
|
, _wlID = n
|
|
, _doorMech = dm
|
|
, _wlColor = c
|
|
, _wlSeen = False
|
|
, _wlIsSeeThrough = False
|
|
, _doorPathable = False
|
|
, _drPositions = DS.fromListL poss
|
|
}
|
|
where
|
|
dm = doorMechan n allZoneps openDoor closeDoor cond
|
|
openDoor = updatePos . (drPositions %~ DS.pushL)
|
|
closeDoor = updatePos . (drPositions %~ DS.pushR)
|
|
updatePos :: Wall -> Wall
|
|
updatePos d = d & wlLine %~ maybe id const (DS.head <$> (d ^? drPositions))
|
|
allZoneps = nub $ concatMap zoneps poss
|