{-# LANGUAGE LambdaCase #-} module Dodge.Damage ( damageCrWl, damageDirection, damageCrWlID, maxDamageType, ) where import Dodge.Data.Damage.Type import Geometry.Vector import ListHelp import Dodge.Data.CrWlID import Dodge.Data.World import qualified IntMapHelp as IM import LensHelp import qualified Data.Map.Strict as M import FoldableHelp damageCrWlID :: Damage -> CrWlID -> World -> World damageCrWlID dam = \case NothingID -> id CrID cid -> cWorld . lWorld . creatures . ix cid . crState . csDamage .:~ dam WlID wlid -> cWorld . lWorld . wallDamages %~ IM.insertWith (++) wlid [dam] damageCrWl :: Damage -> Either Creature Wall -> World -> World damageCrWl dt (Left cr) = cWorld . lWorld . creatures . ix (_crID cr) . crState . csDamage .:~ dt damageCrWl dt (Right wl) = cWorld . lWorld . wallDamages %~ IM.insertWith (++) (_wlID wl) [dt] -- could sort for damage amount as well damageDirection :: [Damage] -> Maybe Float damageDirection ds = safeArgV =<< safeHead (ds ^.. each . dmVector) dmType :: Damage -> DamageType dmType = \case Piercing {} -> PhysicalDamage Blunt {} -> PhysicalDamage Sparking {} -> CookingDamage Crushing {} -> PhysicalDamage Shattering {} -> PhysicalDamage Flaming {} -> CookingDamage Lasering {} -> CookingDamage Flashing {} -> CookingDamage Electrical {} -> CookingDamage Explosive {} -> PhysicalDamage Poison {} -> PoisonDamage Enterrement {} -> PhysicalDamage collectDamageTypes :: [Damage] -> M.Map DamageType Int collectDamageTypes = foldl' (flip f) M.empty where f dm = at (dmType dm) . non 0 +~ _dmAmount dm maxDamageType :: [Damage] -> Maybe (DamageType, Int) maxDamageType = safeMinimumOn (negate . snd) . M.assocs . collectDamageTypes