module Dodge.Spark ( updateSpark, sparkRandDir, randDirSpark, randSpark, randSparkExtraVel, makeSpark, ) where import Control.Monad.State import Dodge.Damage import Dodge.Data.World import Dodge.WorldEvent.ThingsHit import Geometry import LensHelp import System.Random -- should probably reduce spark speed more if it is very fast updateSpark :: World -> Spark -> (World, Maybe Spark) updateSpark w sk | magV (_skVel sk) < 1 = (w, Nothing) | otherwise = case thingHit sp ep w of Nothing -> (w & randGen .~ g, Just $ sk & skPos .~ ep & skVel *~ 0.9 & skVel %~ rotateV a & skOldPos .~ sp) Just (hp, hthing) -> ( sparkDam sk hthing w , Just $ sk & skPos .~ hp & skOldPos .~ sp & skVel .~ 0 ) where (a,g) = randomR (-x,x) (_randGen w) x = 1 sp = _skPos sk ep = sp + _skVel sk sparkDam :: Spark -> Either Creature Wall -> World -> World sparkDam = damageCrWl . sparkToDamage sparkToDamage :: Spark -> [Damage] sparkToDamage sp = case _skType sp of ElectricSpark -> [Electrical 10] FireSpark -> [Flaming 1] NormalSpark -> [Sparking 10] makeSpark :: SparkType -> Point2 -> Float -> World -> World makeSpark st p d = cWorld . lWorld . sparks .:~ Spark { _skVel = rotateV d (V2 5 0) , _skPos = p , _skOldPos = p , _skType = st } randDirSpark :: State StdGen Float -> Point2 -> World -> World randDirSpark randdir pos w = w & randGen .~ g & cWorld . lWorld . sparks .:~ Spark { _skVel = rotateV dir (V2 5 0) , _skPos = pos , _skOldPos = pos , _skType = NormalSpark } where (dir, g) = randdir `runState` _randGen w randSpark :: SparkType -> State StdGen Float -> State StdGen Float -> Point2 -> World -> World randSpark dt randspeed randdir pos w = w & randGen .~ g & cWorld . lWorld . sparks .:~ Spark { _skVel = rotateV dir (V2 speed 0) , _skPos = pos , _skOldPos = pos , _skType = dt } where ((dir, speed), g) = (`runState` _randGen w) $ do d <- randdir x <- randspeed return (d, x) randSparkExtraVel :: Point2 -> SparkType -> State StdGen Float -> State StdGen Float -> Point2 -> World -> World randSparkExtraVel v dt randspeed randdir pos w = w & randGen .~ g & cWorld . lWorld . sparks .:~ Spark { _skVel = v + rotateV dir (V2 speed 0) , _skPos = pos , _skOldPos = pos , _skType = dt } where ((dir, speed), g) = (`runState` _randGen w) $ do d <- randdir x <- randspeed return (d, x) sparkRandDir :: Float -> Point2 -> Float -> World -> World sparkRandDir a pos dir = randDirSpark (state $ randomR (dir - a, dir + a)) pos