Add electrical bullets

This commit is contained in:
2022-03-22 21:45:08 +00:00
parent bda65968b0
commit f030d8264f
10 changed files with 202 additions and 57 deletions
+5 -4
View File
@@ -13,7 +13,7 @@ module Dodge.WorldEvent.Flash
, laserGunFlashAt
, teslaGunFlashAt
, muzFlareAt
, flameFlicker
, ptFlicker
) where
import Dodge.Data
import Dodge.LightSource
@@ -61,8 +61,9 @@ explosionFlashAt p = tempLightSources .:~ tlsTimeRadFunPos 20 150 intensityFunc
| x < 10 = 1 / (10 - fromIntegral x)
| otherwise = 1
flameFlicker :: Particle -> World -> World
flameFlicker pt
ptFlicker :: Particle -> World -> World
ptFlicker pt
| _ptTimer pt `mod` 7 == 0 = tempLightSources
.:~ tlsTimeRadColPos 1 70 (V3 0.5 0 0) (addZ 10 $ _ptPos pt)
.:~ tlsTimeRadColPos 1 70 (0.5 *.*.* xyzV4 (_ptColor pt)) (addZ 10 $ _ptPos pt)
| otherwise = id
+89 -31
View File
@@ -3,6 +3,8 @@ module Dodge.WorldEvent.SpawnParticle
( makeGasCloud
, aFlameParticle
, makeFlamelet
, aStaticBall
, makeStaticBall
) where
import Dodge.Data
import Dodge.Base
@@ -37,7 +39,7 @@ aFlameParticle t pos vel maycid = PtZ
, _ptCrIgnore = maycid
, _ptWidth = 4
, _ptTimer = t
, _ptHitEff = doFlameDamCrWall
, _ptHitEff = damageBothTypeAmount Flaming 20
, _ptZ = 20
}
drawFlame
@@ -80,7 +82,7 @@ moveFlame rotd w pt
| otherwise = case thingsHitExceptCr (_ptCrIgnore pt) sp ep w of
((_,Left _):_) -> (doSound $ damwls damcrs , mvPt 0.7)
((p,Right wl):_) -> (doSound $ damwls damcrs , rfl wl p)
_ -> (flameFlicker pt . damwls $ doSound damcrs , mvPt 0.98)
_ -> (ptFlicker pt . damwls $ doSound damcrs , mvPt 0.98)
where
time = _ptTimer pt
doSound = soundContinue Flame (V2 x y) fireLoudS (Just 2)
@@ -109,6 +111,44 @@ moveFlame rotd w pt
reflV wall = (0.3 *.* reflectIn (uncurry (-.-) . swap $ _wlLine wall) vel )
+.+ (0.2 *.* vel)
aStaticBall :: Point2 -> Particle
aStaticBall vel = PtZ
{ _ptDraw = drawStaticBall
, _ptUpdate = moveStaticBall
, _ptVel = vel
, _ptColor = blue
, _ptPos = 0
, _ptCrIgnore = Nothing
, _ptWidth = 3
, _ptTimer = 20
, _ptHitEff = damageBothTypeAmount Electrical 20
, _ptZ = 20
}
makeStaticBall
:: Point2 -- ^ Position
-> Float -- ^ z position
-> Point2 -- ^ Velocity
-> Maybe Int -- ^ Ignore creature id
-> Float -- ^ Size
-> Int -- ^ Timer
-> World
-> World
makeStaticBall (V2 x y) z vel maycid size time w = w
& instantParticles .:~ PtZ
{ _ptDraw = drawStaticBall
, _ptUpdate = moveStaticBall
, _ptVel = vel
, _ptColor = blue
, _ptPos = V2 x y
, _ptCrIgnore = maycid
, _ptWidth = size
, _ptTimer = time
, _ptHitEff = damageBothTypeAmount Electrical 20
, _ptZ = z
}
makeFlamelet
:: Point2 -- ^ Position
-> Float -- ^ z position
@@ -121,27 +161,42 @@ makeFlamelet
makeFlamelet (V2 x y) z vel maycid size time w = w
& randGen .~ g
& instantParticles .:~ PtZ
{ _ptDraw = drawFlameletZ rot
, _ptUpdate = moveFlamelet
, _ptVel = vel
, _ptColor = red
, _ptPos = V2 x y
, _ptCrIgnore = maycid
, _ptWidth = size
, _ptTimer = time
, _ptHitEff = doFlameDamCrWall
{ _ptDraw = drawFlameletZ rot
, _ptUpdate = moveFlamelet
, _ptVel = vel
, _ptColor = red
, _ptPos = V2 x y
, _ptCrIgnore = maycid
, _ptWidth = size
, _ptTimer = time
, _ptHitEff = damageBothTypeAmount Flaming 20
, _ptZ = z
}
where
(rot ,g) = randomR (0,3) $ _randGen w
doFlameDamCrWall :: Particle
damageBothTypeAmount :: DamageType
-> Int
-> Particle
-> [(Point2, Either Creature Wall)]
-> World
-> (World, Maybe Particle)
doFlameDamCrWall = destroyOnImpact
(doFlameDam 1)
(\_ p -> damageWall (Damage Flaming 19 p p p NoDamageEffect))
damageBothTypeAmount dt amount = destroyOnImpact
(\pt p cr -> creatures . ix (_crID cr) . crState . crDamage .:~ thedam pt p)
(\pt p -> damageWall (thedam pt p))
where
thedam pt p = Damage dt amount sp p ep NoDamageEffect
where
sp = _ptPos pt
ep = sp +.+ _ptVel pt
drawStaticBall
:: Particle
-> Picture
drawStaticBall pt = setLayer 1
. setDepth (_ptZ pt + 20)
. uncurryV translate (_ptPos pt)
$ circleSolidCol (_ptColor pt) (withAlpha 0.5 white) (_ptWidth pt+5)
drawFlameletZ
:: Float -- ^ Rotation
@@ -188,30 +243,33 @@ drawFlameletZ rot pt = pictures
s1 = (*) 2 $ log $ 2 + fromIntegral time / 40
s2 = 0.5 * (sc + s1)
moveStaticBall :: World -> Particle -> (World, Maybe Particle)
moveStaticBall = moveFlamelet
{- Update of a flamelet.
Applies movement and attaches damage to nearby creatures. -}
-- This should be unified in many ways with moveFlame
moveFlamelet :: World -> Particle -> (World, Maybe Particle)
moveFlamelet w pt
| _ptTimer pt <= 0 = ( w, Nothing)
| otherwise = (flameFlicker pt $ damwls damcrs, mvPt)
| otherwise = (ptFlicker pt $ damageInRadius 5 mvPt w, Just mvPt)
where
sp = _ptPos pt
vel = _ptVel pt
ep = sp +.+ vel
size = _ptWidth pt
mvPt = Just $ pt & ptTimer -~ 1
& ptPos .~ ep
& ptCrIgnore .~ Nothing
& ptVel .~ 0.8 *.* vel
damcrs = w & creatures %~ IM.map damifclose
damwls w' = foldr (\wl -> fst . hiteff [(ep,Right wl)]) w' $ IM.filter closeWls $ wallsNearPoint ep w
closeWls wl = uncurry circOnSeg (_wlLine wl) ep 5
mvPt = pt
& ptTimer -~ 1
& ptPos .~ _ptPos pt +.+ _ptVel pt
& ptCrIgnore .~ Nothing
& ptVel .*.*~ 0.8
-- | Note damgeInRadius by itself never destroys the particle
damageInRadius :: Float -> Particle -> World -> World
damageInRadius size pt w = damwls damcrs
where
p = _ptPos pt
damcrs = foldr (\cr -> fst . hiteff [(p,Left cr)]) w $ IM.filter isClose $ _creatures w
damwls w' = foldr (\wl -> fst . hiteff [(p,Right wl)]) w' $ IM.filter closeWls $ wallsNearPoint p w
closeWls wl = uncurry circOnSeg (_wlLine wl) p size
isClose cr = dist p (_crPos cr) < _crRad cr + size
hiteff = _ptHitEff pt pt
isClose cr = dist ep (_crPos cr) < _crRad cr + size
damifclose cr
| isClose cr = cr & crState . crDamage .:~ Damage Flaming 3 sp ep ep NoDamageEffect
| otherwise = cr
-- | At writing the radius is half the size of the effect area
makeGasCloud
:: Point2 -- ^ Position