Files
loop/src/Dodge/Block.hs
T

100 lines
3.3 KiB
Haskell

module Dodge.Block where
import Dodge.Data
import Dodge.Base.Collide
import Dodge.Material
--import Dodge.Block.Debris
import Dodge.Zone
import Dodge.WorldEvent.Sound
import Dodge.Wall.Delete
import Dodge.Wall.Dust
import RandomHelp
import Geometry
--import Geometry.ConvexPoly
import Data.Foldable
import Data.Function
import Data.Maybe
import qualified Data.IntSet as IS
import qualified Data.IntMap.Strict as IM
import Control.Lens
import qualified Streaming.Prelude as S
import qualified Data.Graph.Inductive as FGL
splinterBlock :: Block -> World -> World
splinterBlock bl w = foldr unshadowBlock w (_blShadows bl) -- foldr shiftTowardCen w (_blWallIDs bl)
& originsIDsAt [MaterialSound bm 0,MaterialSound bm 1,MaterialSound bm 2]
(weakenMatS bm) (_blPos bl)
where
bm = fromMaybe Stone $ do
wlids <- w ^? blocks . ix (_blID bl) . blWallIDs
(wlid,_) <- IS.minView wlids
w ^? walls . ix wlid . wlMaterial
unshadowBlock :: Int -> World -> World
unshadowBlock wlid w = case w ^? walls . ix wlid of
Just wl -> w
& walls . ix wlid . wlDraw .~ True
& wlZoning . znObjects . ix x . ix y . ix wlid . wlDraw .~ True
where
V2 x y = wlZoneOfPoint $ uncurry midPoint (_wlLine wl)
Nothing -> w
checkBlockHP :: Block -> World -> World
checkBlockHP bl
| _blHP bl < 1 = destroyBlock bl
| otherwise = id
destroyBlock :: Block -> World -> World
destroyBlock bl w = w
& flip (foldr unshadowBlock) (_blShadows bl)
& _blDeath bl bl
& deleteWallIDs wlids
& maybeClearPaths (_blObstructs bl) -- must happen after the walls are deleted
& blocks %~ IM.delete (_blID bl)
-- & matDesSound (_blMaterial bl) pos
& flip (foldr (wlDustAt awl)) (map (pos +.+) ps)
where
wlids = _blWallIDs bl
awl = _walls w IM.! IS.findMin wlids
pos = fst . _wlLine $ _walls w IM.! IS.findMin wlids
ps = replicateM 25 (randInCirc 20) & evalState $ _randGen w
-- this does not handle eg doors blocking the path as well
maybeClearPaths :: [(Int,Int,PathEdge)] -> World -> World
maybeClearPaths ps w = foldl' maybeClearPath w ps
maybeClearPath :: World -> (Int,Int,PathEdge) -> World
maybeClearPath w (x,y,pe)
| runIdentity . S.any_ (const True) $ overlapSegWalls (_peStart pe) (_peEnd pe) $ wlsNearSeg (_peStart pe) (_peEnd pe) w
= w
| otherwise = w & pathGraph %~ FGL.insEdge (x,y,pe & peObstacles .~ mempty) . FGL.delEdge (x,y)
destroyDoor :: Door -> World -> World
destroyDoor dr w = w
& _drDeath dr dr
& deleteWallIDs wlids
& doors %~ IM.delete (_drID dr)
& flip (foldr (wlDustAt awl)) (map (pos +.+) ps)
& stopPushing (_drPushes dr)
& destroyMounts (_drMounts dr)
where
wlids = _drWallIDs dr
awl = _walls w IM.! IS.findMin wlids
pos = fst . _wlLine $ _walls w IM.! IS.findMin wlids
ps = replicateM 25 (randInCirc 20) & evalState $ _randGen w
destroyMounts :: [MountedObject] -> World -> World
destroyMounts mos w = foldr destroyMount w mos
destroyMount :: MountedObject -> World -> World
destroyMount mo = case mo of
MountedLS lsid -> lightSources . at lsid .~ Nothing
MountedProp prid -> props . at prid .~ Nothing
stopPushing :: Maybe Int -> World -> World
stopPushing mdrid w = fromMaybe w $ do
drid <- mdrid
dr <- w ^? doors . ix drid
return $ w & doors . ix drid . drMech .~ const id
& stopPushing (_drPushes dr)