Files
loop/src/Dodge/Creature/Action/Blink.hs
T
2026-03-26 19:21:10 +00:00

104 lines
3.5 KiB
Haskell

{-# LANGUAGE TupleSections #-}
module Dodge.Creature.Action.Blink (
blinkActionMousePos,
blinkActionFail,
unsafeBlinkAction,
) where
import qualified Data.IntMap.Strict as IM
import Linear
import Dodge.Creature.Radius
import Dodge.Zoning.Wall
import Data.Maybe
import Dodge.Base
import Dodge.Data.World
import Dodge.SoundLogic
import Dodge.WorldEvent.Shockwave
import Geometry
import LensHelp
import Picture
-- note collideCircWalls doesn't always correctly zone walls, this should be
-- replaced.
-- I think the test circHitWall DOES work
-- | Teleport a creature to the mouse position
blinkActionMousePos :: Creature -> World -> World
blinkActionMousePos cr w =
w
& soundMultiFrom [TeleSound 0, TeleSound 1] p3 teleS Nothing
& blinkDistortions cpos p3
& cWorld . lWorld . creatures . ix cid . crPos . _xy .~ p3
& blinkShockwave cid p3
& inverseShockwaveAt (cpos `v2z` 20) 40 2 2
where
cid = _crID cr
p1 = w ^. cWorld . lWorld . lAimPos
cpos = cr ^. crPos . _xy
--p2 = bouncePoint (const True) 1 cpos p1 w
p2 = pushIntoMaybe $ collideCircWalls cpos p1 r (IM.elems $ wlsNearSeg cpos p1 w)
r = crRad $ cr ^. crType
p3 = maybe p1 ((+.+ squashNormalizeV (cpos -.- p1)) . fst) p2
--p3 = maybe p1 (const 0) p2
--p3 = maybe p1 fst p2
pushIntoMaybe :: (a, Maybe b) -> Maybe (a,b)
pushIntoMaybe (x,my) = (x,) <$> my
blinkDistortions :: Point2 -> Point2 -> World -> World
blinkDistortions _ _ = id
--blinkDistortions sp ep = cWorld . lWorld . distortions .++~ distortionBulge
-- where
-- distR = 120
-- distortionBulge =
-- [ RadialDistortion ep (ep +.+ V2 distR 0) (ep +.+ V2 0 distR) 0.1
-- , RadialDistortion sp (sp +.+ V2 distR 0) (sp +.+ V2 0 distR) 1.9
-- ]
{- | Teleport a creature to the mouse position.
Can go through walls, if ending up in wall does big damage.
-}
unsafeBlinkAction :: Creature -> World -> World
unsafeBlinkAction cr w
| success =
soundMultiFrom [TeleSound 0, TeleSound 1] mwp teleS Nothing
. blinkDistortions cpos mwp
. set (cWorld . lWorld . creatures . ix cid . crPos . _xy) mwp
. blinkShockwave cid mwp
$ inverseShockwaveAt (cpos `v2z` 20) 40 2 2 w
| otherwise =
w
& blinkActionFail cr
& cWorld . lWorld . creatures . ix cid . crDamage .:~ Enterrement 100000000
where
success = fromMaybe True $ do
wl <- snd $ collidePointWallsFilter (const True) mwp cpos w
return (isLHS mwp `uncurry` _wlLine wl)
cid = _crID cr
mwp = w ^. cWorld . lWorld . lAimPos
cpos = cr ^. crPos . _xy
blinkShockwave ::
-- | Blinking creature ID.
Int ->
Point2 ->
World ->
World
blinkShockwave i p = makeShockwaveAt [i] (p `v2z` 20) 60 1 2 cyan
-- | Like a blink action, but no ingoing distortion
blinkActionFail :: Creature -> World -> World
blinkActionFail cr w =
w
& soundMultiFrom [TeleSound 0, TeleSound 1] p3 teleS Nothing
-- & cWorld . lWorld . distortions .:~ distortionBulge
& cWorld . lWorld . creatures . ix cid . crPos . _xy .~ p3
& inverseShockwaveAt (cpos `v2z` 20) 40 2 2
where
-- distR = 120
-- distortionBulge = RadialDistortion cpos (cpos +.+ V2 distR 0) (cpos +.+ V2 0 distR) 1.9
cid = _crID cr
p1 = w ^. cWorld . lWorld . lAimPos
cpos = cr ^. crPos . _xy
p2 = bouncePoint (const True) 1 cpos p1 w
r = 1.5 * crRad (cr ^. crType)
p3 = maybe p1 (mvPointTowardAtSpeed r cpos . fst) p2