module Dodge.WorldEvent.HitEffect where import Dodge.Data import Dodge.Data.DamageType import Dodge.Creature.State.Data import Geometry import Data.Bifunctor import Data.Maybe import Control.Lens type HitCreatureEffect = Particle -> Point2 -> Creature -> World -> World type HitWallEffect = Particle -> Point2 -> Wall -> World -> World type HitForceFieldEffect = Particle -> Point2 -> ForceField -> World -> World passThroughAll :: HitCreatureEffect -> HitWallEffect -> HitForceFieldEffect -> Particle -> [(Point2, Either3 Creature Wall ForceField)] -- ^ hit things -> World -> (World, Maybe Particle) passThroughAll _ _ _ pt _ w = (w, mvPt) where mvPt = Just $ pt & btTrail' .~ (newP : trl) & btTimer' %~ (\t -> t - 1) & btPassThrough' .~ Nothing trl = _btTrail' pt newP = head trl +.+ _btVel' pt destroyOnImpact :: HitCreatureEffect -> HitWallEffect -> HitForceFieldEffect -> Particle -> [(Point2, Either3 Creature Wall ForceField)] -> World -> (World, Maybe Particle) destroyOnImpact crEff wlEff ffEff pt hitThings w = case hitThings of [] -> ( w, mvPt) ((p,E3x1 cr):_) -> (crEff pt p cr w, destroyAt p) ((p,E3x2 wl):_) -> (wlEff pt p wl w, destroyAt p) ((p,E3x3 ff):_) -> (ffEff pt p ff w, destroyAt p) where destroyAt hitp = Just $ pt & btTrail' .~ (hitp : trl) & btTimer' .~ 3 mvPt = Just $ pt & btTrail' .~ (newP : trl) & btTimer' %~ (\t -> t - 1) & btPassThrough' .~ Nothing trl = _btTrail' pt newP = head trl +.+ _btVel' pt penWalls :: HitCreatureEffect -> HitWallEffect -> HitForceFieldEffect -> Particle -> [(Point2, Either3 Creature Wall ForceField)] -> World -> (World, Maybe Particle) penWalls crEff wlEff ffEff pt hitThings w = case hitThings of [] -> ( w, mvPt) ((p,E3x1 cr):_) -> (crEff pt p cr w, destroyAt p) ((p,E3x3 ff):_) -> (ffEff pt p ff w, destroyAt p) ((p,E3x2 wl):hs) | isJust (wl ^? wlBlockID) -> first (wlEff pt p wl) $ penWalls crEff wlEff ffEff pt hs w ((p,E3x2 wl):_) | otherwise -> (wlEff pt p wl w, destroyAt p) where destroyAt hitp = Just $ pt & btTrail' .~ (hitp : trl) & btTimer' .~ 3 mvPt = Just $ pt & btTrail' .~ (newP : trl) & btTimer' %~ (\t -> t - 1) & btPassThrough' .~ Nothing trl = _btTrail' pt newP = head trl +.+ _btVel' pt doFlameDam :: Int -> Particle -> Point2 -> Creature -> World -> World doFlameDam amount pt p cr = over (creatures . ix (_crID cr) . crState . crDamage) ((:) $ Flaming amount sp p ep) where sp = _btPos' pt ep = sp +.+ _btVel' pt noEff :: a -> b -> c -> d -> d noEff _ _ _ = id