Files
loop/src/Dodge/Room/SensorDoor.hs
T
2026-03-21 18:48:44 +00:00

103 lines
3.3 KiB
Haskell

{-# LANGUAGE TupleSections #-}
module Dodge.Room.SensorDoor (sensAboveDoor, sensorRoomRunPast) where
import Control.Monad
import qualified Data.Set as S
import Dodge.Cleat
import Dodge.Data.GenWorld
import Dodge.Data.MTRS
import Dodge.LevelGen.PlacementHelper
import Dodge.Placement.Instance
import Dodge.PlacementSpot
import Dodge.Room.Corridor
import Dodge.Room.Door
import Dodge.Room.Link
import Dodge.Room.Modify
import Dodge.Room.Ngon
import Dodge.Room.Procedural
import Dodge.RoomLink
import Dodge.Terminal
import Dodge.Tree
import Dodge.Wire
import Geometry
import LensHelp
import RandomHelp
-- TODO fix case where the sensor created by sensInsideDoor blocks another door
-- for roomRectAutoLinks-- make the locked door a center door?
sensorRoom :: SensorType -> Int -> State LayoutVars (Tree Room)
sensorRoom senseType n = do
rm <-
join $
takeOne
[ addLightsNGon =<< roomNgon 8 200
, roomRectAutoLights 200 200 <&> rmLinks %~ setOutLinks nonCornerLinks
]
cenroom <- shuffleLinks $ sensInsideDoor senseType n rm
return $
treePost
[ door
, cenroom & rmLinkEff .~ f
, triggerDoorRoom n
, cleatOnward door
]
where
f _ _ 0 rl rm = rm & rmLinks %~ map (g (_rlPos rl) (_rlDir rl))
f _ _ _ _ rm = rm
g p d rl
| isclose = rl & rlType . at BlockedLink ?~ ()
| otherwise = rl
where
p' = p +.+ rotateV d (V2 0 (negate 100))
isclose = dist (_rlPos rl) p' < 30
nonCornerLinks :: RoomLink -> Bool
nonCornerLinks = not . any f . (^. rlType)
where
f (FromEdge _ 0) = True
f _ = False
sensorRoomRunPast :: SensorType -> Int -> State LayoutVars MTRS
sensorRoomRunPast dt n = do
t <- sensorRoom dt n
rToOnward "sensorRoomRunPast" $
t
& applyToSubforest
[0]
(++ [treePost [door & rmConnectsTo .~ (\s -> S.member InLink s && not (S.member BlockedLink s)), cleatLabel n corridor]])
sensAboveDoor :: SensorType -> Float -> PlacementSpot -> Placement
sensAboveDoor sensetype wth ps =
extTrigLitPos
( psposAddLabel
ColoredLightRP
(atFstLnkOutShiftBy (\(p, a) -> ((p +.+ rotateV a (V2 18.5 (-2.5)), a), S.singleton UsedPosHigh)))
)
(\tp -> Just $ damageSensor sensetype wth (_plMID tp) ps)
sensInsideDoor :: SensorType -> Int -> Room -> Room
sensInsideDoor senseType i rm =
rm
& rmName
.++~ take 4 (show senseType)
& rmPmnts
.++~ [ psPt atFstLnkOut . PutForeground $ floorWire (V2 20 0) (V2 20 (-100))
, psPt atFstLnkOut . PutForeground $ floorWire (V2 0 (-100)) (V2 20 (-100))
, psPt atFstLnkOut . PutForeground $ verticalWire (V2 20 0) 0 80
, putMessageTerminal
(textTerminal & tmCommands .:~ TCDamageCommand)
& plSpot
.~ rprBoolShift termpos (shiftInBy 10 <&> (,S.singleton UsedPosHigh))
, sensAboveDoor senseType 10 (atFstLnkOutShiftInward 100) & plExternalID ?~ i
]
where
termpos rp rm' =
isUnusedLnk rp rm'
&& all ((> 30) . dist (_rpPos rp) . _rpPos) (filter usedlnks $ rm' ^. rmPos)
usedlnks rp = case _rpType rp of
UsedOutLink{} -> True
UsedInLink{} -> True
UnusedLink{} -> False
NotLink{} -> False