-- | Blast definitions.
module Content.ItemKindBlast
  ( -- * Group name patterns
    pattern S_FIRECRACKER, pattern S_VIOLENT_FRAGMENTATION, pattern S_FRAGMENTATION, pattern S_FOCUSED_FRAGMENTATION, pattern S_VIOLENT_CONCUSSION, pattern S_CONCUSSION, pattern S_FOCUSED_CONCUSSION, pattern S_VIOLENT_FLASH, pattern S_FOCUSED_FLASH, pattern S_GLASS_HAIL, pattern S_FOCUSED_GLASS_HAIL, pattern S_PHEROMONE, pattern S_CALMING_MIST, pattern S_DISTRESSING_ODOR, pattern S_HEALING_MIST, pattern S_HEALING_MIST_2, pattern S_WOUNDING_MIST, pattern S_DISTORTION, pattern S_SMOKE, pattern S_BOILING_WATER, pattern S_GLUE, pattern S_WASTE, pattern S_ANTI_SLOW_MIST, pattern S_ANTIDOTE_MIST, pattern S_SLEEP_MIST, pattern S_DENSE_SHOWER, pattern S_SPARSE_SHOWER, pattern S_MELEE_PROTECTIVE_BALM, pattern S_RANGE_PROTECTIVE_BALM, pattern S_DEFENSELESSNESS_RUNOUT, pattern S_RESOLUTION_DUST, pattern S_HASTE_SPRAY, pattern S_VIOLENT_SLOWNESS_MIST, pattern S_SLOWNESS_MIST, pattern S_FOCUSED_SLOWNESS_MIST, pattern S_EYE_DROP, pattern S_IRON_FILING, pattern S_SMELLY_DROPLET, pattern S_EYE_SHINE, pattern S_WHISKEY_SPRAY, pattern S_YOUTH_SPRINKLE, pattern S_POISON_CLOUD, pattern S_PING_PLASH, pattern S_VIOLENT_BURNING_OIL_2, pattern S_VIOLENT_BURNING_OIL_3, pattern S_VIOLENT_BURNING_OIL_4, pattern S_BURNING_OIL_2, pattern S_BURNING_OIL_3, pattern S_BURNING_OIL_4, pattern S_FOCUSED_BURNING_OIL_2, pattern S_FOCUSED_BURNING_OIL_3, pattern S_FOCUSED_BURNING_OIL_4
  , blastNoStatOf, blastBonusStatOf
  , pattern ARMOR_MISC
  , blastsGNSingleton, blastsGN
  , -- * Content
    blasts
  ) where

import Prelude ()

import Game.LambdaHack.Core.Prelude

import Game.LambdaHack.Content.ItemKind
import Game.LambdaHack.Core.Dice
import Game.LambdaHack.Definition.Ability
import Game.LambdaHack.Definition.Color
import Game.LambdaHack.Definition.Defs
import Game.LambdaHack.Definition.DefsInternal
import Game.LambdaHack.Definition.Flavour

import Content.ItemKindTemporary

-- * Group name patterns

blastsGNSingleton :: [GroupName ItemKind]
blastsGNSingleton =
       [S_FIRECRACKER, S_VIOLENT_FRAGMENTATION, S_FRAGMENTATION, S_FOCUSED_FRAGMENTATION, S_VIOLENT_CONCUSSION, S_CONCUSSION, S_FOCUSED_CONCUSSION, S_VIOLENT_FLASH, S_FOCUSED_FLASH, S_GLASS_HAIL, S_FOCUSED_GLASS_HAIL, S_PHEROMONE, S_CALMING_MIST, S_DISTRESSING_ODOR, S_HEALING_MIST, S_HEALING_MIST_2, S_WOUNDING_MIST, S_DISTORTION, S_SMOKE, S_BOILING_WATER, S_GLUE, S_WASTE, S_ANTI_SLOW_MIST, S_ANTIDOTE_MIST, S_SLEEP_MIST, S_DENSE_SHOWER, S_SPARSE_SHOWER, S_MELEE_PROTECTIVE_BALM, S_RANGE_PROTECTIVE_BALM, S_DEFENSELESSNESS_RUNOUT, S_RESOLUTION_DUST, S_HASTE_SPRAY, S_VIOLENT_SLOWNESS_MIST, S_SLOWNESS_MIST, S_FOCUSED_SLOWNESS_MIST, S_EYE_DROP, S_IRON_FILING, S_SMELLY_DROPLET, S_EYE_SHINE, S_WHISKEY_SPRAY, S_YOUTH_SPRINKLE, S_POISON_CLOUD, S_PING_PLASH, S_VIOLENT_BURNING_OIL_2, S_VIOLENT_BURNING_OIL_3, S_VIOLENT_BURNING_OIL_4, S_BURNING_OIL_2, S_BURNING_OIL_3, S_BURNING_OIL_4, S_FOCUSED_BURNING_OIL_2, S_FOCUSED_BURNING_OIL_3, S_FOCUSED_BURNING_OIL_4]
  ++ map firecrackerAt [1..4]
  ++ map blastNoStatOf noStatGN
  ++ map blastBonusStatOf bonusStatGN

pattern S_FIRECRACKER, S_VIOLENT_FRAGMENTATION, S_FRAGMENTATION, S_FOCUSED_FRAGMENTATION, S_VIOLENT_CONCUSSION, S_CONCUSSION, S_FOCUSED_CONCUSSION, S_VIOLENT_FLASH, S_FOCUSED_FLASH, S_GLASS_HAIL, S_FOCUSED_GLASS_HAIL, S_PHEROMONE, S_CALMING_MIST, S_DISTRESSING_ODOR, S_HEALING_MIST, S_HEALING_MIST_2, S_WOUNDING_MIST, S_DISTORTION, S_SMOKE, S_BOILING_WATER, S_GLUE, S_WASTE, S_ANTI_SLOW_MIST, S_ANTIDOTE_MIST, S_SLEEP_MIST, S_DENSE_SHOWER, S_SPARSE_SHOWER, S_MELEE_PROTECTIVE_BALM, S_RANGE_PROTECTIVE_BALM, S_DEFENSELESSNESS_RUNOUT, S_RESOLUTION_DUST, S_HASTE_SPRAY, S_VIOLENT_SLOWNESS_MIST, S_SLOWNESS_MIST, S_FOCUSED_SLOWNESS_MIST, S_EYE_DROP, S_IRON_FILING, S_SMELLY_DROPLET, S_EYE_SHINE, S_WHISKEY_SPRAY, S_YOUTH_SPRINKLE, S_POISON_CLOUD, S_PING_PLASH, S_VIOLENT_BURNING_OIL_2, S_VIOLENT_BURNING_OIL_3, S_VIOLENT_BURNING_OIL_4, S_BURNING_OIL_2, S_BURNING_OIL_3, S_BURNING_OIL_4, S_FOCUSED_BURNING_OIL_2, S_FOCUSED_BURNING_OIL_3, S_FOCUSED_BURNING_OIL_4 :: GroupName ItemKind

blastsGN :: [GroupName ItemKind]
blastsGN =
       [ARMOR_MISC]

pattern ARMOR_MISC :: GroupName ItemKind

pattern S_FIRECRACKER = GroupName "firecracker"
pattern S_VIOLENT_FRAGMENTATION = GroupName "violent fragmentation"
pattern S_FRAGMENTATION = GroupName "fragmentation"
pattern S_FOCUSED_FRAGMENTATION = GroupName "focused fragmentation"
pattern S_VIOLENT_CONCUSSION = GroupName "violent concussion"
pattern S_CONCUSSION = GroupName "concussion"
pattern S_FOCUSED_CONCUSSION = GroupName "focused concussion"
pattern S_VIOLENT_FLASH = GroupName "violent flash"
pattern S_FOCUSED_FLASH = GroupName "focused flash"
pattern S_GLASS_HAIL = GroupName "glass hail"
pattern S_FOCUSED_GLASS_HAIL = GroupName "focused glass hail"
pattern S_PHEROMONE = GroupName "pheromone"
pattern S_CALMING_MIST = GroupName "calming mist"
pattern S_DISTRESSING_ODOR = GroupName "distressing odor"
pattern S_HEALING_MIST = GroupName "healing mist"
pattern S_HEALING_MIST_2 = GroupName "strong healing mist"
pattern S_WOUNDING_MIST = GroupName "wounding mist"
pattern S_DISTORTION = GroupName "distortion"
pattern S_SMOKE = GroupName "smoke"
pattern S_BOILING_WATER = GroupName "boiling water"
pattern S_GLUE = GroupName "glue"
pattern S_WASTE = GroupName "waste"
pattern S_ANTI_SLOW_MIST = GroupName "anti-slow mist"
pattern S_ANTIDOTE_MIST = GroupName "antidote mist"
pattern S_SLEEP_MIST = GroupName "sleep mist"
pattern S_DENSE_SHOWER = GroupName "dense shower"
pattern S_SPARSE_SHOWER = GroupName "sparse shower"
pattern S_MELEE_PROTECTIVE_BALM = GroupName "melee protective balm"
pattern S_RANGE_PROTECTIVE_BALM = GroupName "ranged protective balm"
pattern S_DEFENSELESSNESS_RUNOUT = GroupName "PhD defense question"
pattern S_RESOLUTION_DUST = GroupName "resolution dust"
pattern S_HASTE_SPRAY = GroupName "haste spray"
pattern S_VIOLENT_SLOWNESS_MIST = GroupName "violent nitrogen mist"
pattern S_SLOWNESS_MIST = GroupName "nitrogen mist"
pattern S_FOCUSED_SLOWNESS_MIST = GroupName "focused nitrogen mist"
pattern S_EYE_DROP = GroupName "eye drop"
pattern S_IRON_FILING = GroupName "iron filing"
pattern S_SMELLY_DROPLET = GroupName "smelly droplet"
pattern S_EYE_SHINE = GroupName "eye shine"
pattern S_WHISKEY_SPRAY = GroupName "whiskey spray"
pattern S_YOUTH_SPRINKLE = GroupName "youth sprinkle"
pattern S_POISON_CLOUD = GroupName "poison cloud"
pattern S_PING_PLASH = GroupName "ping and flash"
pattern S_VIOLENT_BURNING_OIL_2 = GroupName "violent burning oil 2"
pattern S_VIOLENT_BURNING_OIL_3 = GroupName "violent burning oil 3"
pattern S_VIOLENT_BURNING_OIL_4 = GroupName "violent burning oil 4"
pattern S_BURNING_OIL_2 = GroupName "burning oil 2"
pattern S_BURNING_OIL_3 = GroupName "burning oil 3"
pattern S_BURNING_OIL_4 = GroupName "burning oil 4"
pattern S_FOCUSED_BURNING_OIL_2 = GroupName "focused burning oil 2"
pattern S_FOCUSED_BURNING_OIL_3 = GroupName "focused burning oil 3"
pattern S_FOCUSED_BURNING_OIL_4 = GroupName "focused burning oil 4"

firecrackerAt :: Int -> GroupName ItemKind
firecrackerAt n = GroupName $ "firecracker" <+> tshow n

blastNoStatOf :: GroupName ItemKind -> GroupName ItemKind
blastNoStatOf grp = GroupName $ fromGroupName grp <+> "mist"

blastBonusStatOf :: GroupName ItemKind -> GroupName ItemKind
blastBonusStatOf grp = GroupName $ fromGroupName grp <+> "dew"

pattern ARMOR_MISC = GroupName "miscellaneous armor"

-- * Content

blasts :: [ItemKind]
blasts =
  [spreadBurningOil2, spreadBurningOil3, spreadBurningOil4, spreadBurningOil82, spreadBurningOil83, spreadBurningOil84, focusedBurningOil2, focusedBurningOil3, focusedBurningOil4, firecracker1, firecracker2, firecracker3, firecracker4, firecracker5, spreadFragmentation, spreadFragmentation8, focusedFragmentation, spreadConcussion, spreadConcussion8, focusedConcussion, spreadFlash, spreadFlash8, focusedFlash, singleSpark, glassPiece, focusedGlass, fragrance, pheromone, mistCalming, odorDistressing, mistHealing, mistHealing2, mistWounding, distortion, smoke, boilingWater, glue, waste, mistAntiSlow, mistAntidote, mistSleep, denseShower, sparseShower, protectingBalmMelee, protectingBalmRanged, defenselessnessRunout, resolutionDust, hasteSpray, spreadNitrogen, spreadNitrogen8, focusedNitrogen, eyeDrop, ironFiling, smellyDroplet, eyeShine, whiskeySpray, youthSprinkle, poisonCloud, pingFlash, blastNoSkMove, blastNoSkMelee, blastNoSkDisplace, blastNoSkAlter, blastNoSkWait, blastNoSkMoveItem, blastNoSkProject, blastNoSkApply, blastBonusSkMove, blastBonusSkMelee, blastBonusSkDisplace, blastBonusSkAlter, blastBonusSkWait, blastBonusSkMoveItem, blastBonusSkProject, blastBonusSkApply]

spreadBurningOil2,    spreadBurningOil3, spreadBurningOil4, spreadBurningOil82, spreadBurningOil83, spreadBurningOil84, focusedBurningOil2, focusedBurningOil3, focusedBurningOil4, firecracker1, firecracker2, firecracker3, firecracker4, firecracker5, spreadFragmentation, spreadFragmentation8, focusedFragmentation, spreadConcussion, spreadConcussion8, focusedConcussion, spreadFlash, spreadFlash8, focusedFlash, singleSpark, glassPiece, focusedGlass, fragrance, pheromone, mistCalming, odorDistressing, mistHealing, mistHealing2, mistWounding, distortion, smoke, boilingWater, glue, waste, mistAntiSlow, mistAntidote, mistSleep, denseShower, sparseShower, protectingBalmMelee, protectingBalmRanged, defenselessnessRunout, resolutionDust, hasteSpray, spreadNitrogen, spreadNitrogen8, focusedNitrogen,  eyeDrop, ironFiling, smellyDroplet, eyeShine, whiskeySpray, youthSprinkle, poisonCloud, pingFlash, blastNoSkMove, blastNoSkMelee, blastNoSkDisplace, blastNoSkAlter, blastNoSkWait, blastNoSkMoveItem, blastNoSkProject, blastNoSkApply, blastBonusSkMove, blastBonusSkMelee, blastBonusSkDisplace, blastBonusSkAlter, blastBonusSkWait, blastBonusSkMoveItem, blastBonusSkProject, blastBonusSkApply :: ItemKind

-- We take care (e.g., in burningOil below) that blasts are not faster
-- than 100% fastest natural speed, or some frames would be skipped,
-- which is a waste of perfectly good frames.

-- * Parameterized blasts

spreadBurningOil :: Int -> GroupName ItemKind -> ItemKind
spreadBurningOil n grp = ItemKind
  { isymbol  = toContentSymbol '*'
  , iname    = "burning oil"
  , ifreq    = [(grp, 1)]
  , iflavour = zipPlain [BrYellow]
  , icount   = intToDice (4 + n * 2)
  , irarity  = [(1, 1)]
  , iverbHit = "sear"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toVelocity (max 10 $ min 100 $ n `div` 2 * 10)
               , SetFlag Fragile, SetFlag Blast
               , AddSkill SkShine 2 ]
  , ieffects = [ Burn 1
               , toOrganBad S_PACIFIED (2 + 1 `d` 2) ]
                   -- slips and frantically puts out fire
  , idesc    = "Sticky oil, burning brightly."
  , ikit     = []
  }
spreadBurningOil2 = spreadBurningOil 2 S_VIOLENT_BURNING_OIL_2
                      -- 2 steps, 2 turns
spreadBurningOil3 = spreadBurningOil 3 S_VIOLENT_BURNING_OIL_3
                      -- 2 steps, 2 turns
spreadBurningOil4 = spreadBurningOil 4 S_VIOLENT_BURNING_OIL_4
                      -- 4 steps, 2 turns
spreadBurningOil8 :: Int -> GroupName ItemKind -> ItemKind
spreadBurningOil8 n grp = (spreadBurningOil (n `div` 2) grp)
  { icount   = 7  -- 8 was too deadly
  }
spreadBurningOil82 = spreadBurningOil8 2 S_BURNING_OIL_2
spreadBurningOil83 = spreadBurningOil8 3 S_BURNING_OIL_3
spreadBurningOil84 = spreadBurningOil8 4 S_BURNING_OIL_4
focusedBurningOil :: Int -> GroupName ItemKind -> GroupName ItemKind -> ItemKind
focusedBurningOil n grp grpExplode = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "igniting oil"
  , ifreq    = [(grp, 1)]
  , iflavour = zipPlain [BrYellow]  -- all ignitions yellow to avoid appearing
                                    -- as a small vial explosion
  , icount   = intToDice n
  , irarity  = [(1, 1)]
  , iverbHit = "ignite"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toLinger 0  -- 0 steps, 1 turn
               , SetFlag Fragile, SetFlag Blast ]
      -- when the target position is occupied, the explosion starts one step
      -- away, hence we set range to 0 steps, to limit dispersal
  , ieffects = [OnSmash $ Explode grpExplode]
  , idesc    = idesc spreadBurningOil2
  , ikit     = []
  }
focusedBurningOil2 = focusedBurningOil 2 S_FOCUSED_BURNING_OIL_2 S_BURNING_OIL_2
focusedBurningOil3 = focusedBurningOil 3 S_FOCUSED_BURNING_OIL_3 S_BURNING_OIL_3
focusedBurningOil4 = focusedBurningOil 4 S_FOCUSED_BURNING_OIL_4 S_BURNING_OIL_4
firecracker :: Int -> ItemKind
firecracker n = ItemKind
  { isymbol  = toContentSymbol '*'
  , iname    = "firecracker"
  , ifreq    = [(if n == 5
                 then S_FIRECRACKER
                 else firecrackerAt n, 1)]
  , iflavour = zipPlain [brightCol !! ((n + 2) `mod` length brightCol)]
  , icount   = if n <= 3 then 1 `d` min 2 n else 2 + 1 `d` 2
  , irarity  = [(1, 1)]
  , iverbHit = if n >= 4 then "singe" else "crack"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toVelocity 5  -- 1 step, 1 turn
               , SetFlag Fragile, SetFlag Blast
               , AddSkill SkShine $ intToDice $ 1 + n `div` 2 ]
  , ieffects = [if n >= 4 then Burn 1 else RefillCalm (-2)]
               ++ [Discharge 1 30 | n >= 3]
               ++ [OnSmash $ Explode $ firecrackerAt (n - 1) | n >= 2]
  , idesc    = "Scraps of burnt paper, covering little pockets of black powder, buffeted by colorful explosions."
  , ikit     = []
  }
firecracker5 = firecracker 5
firecracker4 = firecracker 4
firecracker3 = firecracker 3
firecracker2 = firecracker 2
firecracker1 = firecracker 1

-- * Focused blasts

spreadFragmentation = ItemKind
  { isymbol  = toContentSymbol '*'
  , iname    = "fragmentation burst"
  , ifreq    = [(S_VIOLENT_FRAGMENTATION, 1)]
  , iflavour = zipPlain [Red]
  , icount   = 8  -- strong but few, so not always hits target
  , irarity  = [(1, 1)]
  , iverbHit = "tear apart"
  , iweight  = 1
  , idamage  = 3 `d` 1  -- deadly and adjacent actor hit by 2 on average;
                        -- however, moderate armour blocks completely
  , iaspects = [ ToThrow $ ThrowMod 100 20 4  -- 4 steps, 1 turn
               , SetFlag Lobable, SetFlag Fragile, SetFlag Blast
               , AddSkill SkShine 3, AddSkill SkHurtMelee $ -12 * 5 ]
  , ieffects = [DropItem 1 1 COrgan CONDITION]
  , idesc    = "Flying shards, flame and smoke."
  , ikit     = []
  }
spreadFragmentation8 = spreadFragmentation
  { ifreq    = [(S_FRAGMENTATION, 1)]
  , icount   = 5
  , iaspects = [ ToThrow $ ThrowMod 100 10 2  -- 2 steps, 1 turn
               , SetFlag Lobable, SetFlag Fragile, SetFlag Blast
               , AddSkill SkShine 3, AddSkill SkHurtMelee $ -12 * 5 ]
      -- smaller radius, so worse for area effect, but twice the direct damage
  }
focusedFragmentation = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "deflagration ignition"  -- black powder
  , ifreq    = [(S_FOCUSED_FRAGMENTATION, 1)]
  , iflavour = zipPlain [BrYellow]
  , icount   = 3  -- 15 in total vs 8, higher spread
  , irarity  = [(1, 1)]
  , iverbHit = "ignite"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toLinger 0  -- 0 steps, 1 turn
               , SetFlag Fragile, SetFlag Blast ]
      -- when the target position is occupied, the explosion starts one step
      -- away, hence we set range to 0 steps, to limit dispersal
  , ieffects = [OnSmash $ Explode S_FRAGMENTATION]
  , idesc    = idesc spreadFragmentation
  , ikit     = []
  }
spreadConcussion = ItemKind
  { isymbol  = toContentSymbol '*'
  , iname    = "concussion blast"
  , ifreq    = [(S_VIOLENT_CONCUSSION, 1)]
  , iflavour = zipPlain [Magenta]
  , icount   = 12  -- pushing sometimes gets the victim out of attacker range,
                   -- but also sometimes moves to a position hit again later
  , irarity  = [(1, 1)]
  , iverbHit = "shock"
  , iweight  = 1
  , idamage  = 1 `d` 1  -- only air pressure, so not as deadly as fragmentation,
                        -- but armour can't block completely that easily
  , iaspects = [ ToThrow $ ThrowMod 100 20 4  -- 4 steps, 1 turn
               , SetFlag Lobable, SetFlag Fragile, SetFlag Blast
               , AddSkill SkShine 3, AddSkill SkHurtMelee $ -8 * 5 ]
      -- outdoors it has short range, but we only model indoors in the game;
      -- it's much faster than black powder shock wave, but we are beyond
      -- human-noticeable speed differences on short distances anyway
  , ieffects = [ DropItem maxBound 1 CEqp ARMOR_MISC
               , PushActor (ThrowMod 400 25 1)  -- 1 step, fast; after DropItem
                   -- this produces spam for braced actors; too bad
               , toOrganBad S_IMMOBILE 1  -- no balance
               , toOrganBad S_DEAFENED 23 ]
  , idesc    = "Shock wave, hot gases, some fire and smoke."
  , ikit     = []
  }
spreadConcussion8 = spreadConcussion
  { ifreq    = [(S_CONCUSSION, 1)]
  , icount   = 6
  , iaspects = [ ToThrow $ ThrowMod 100 10 2  -- 2 steps, 1 turn
               , SetFlag Lobable, SetFlag Fragile, SetFlag Blast
               , AddSkill SkShine 3, AddSkill SkHurtMelee $ -8 * 5 ]
  }
focusedConcussion = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "detonation ignition"  -- nitroglycerine
  , ifreq    = [(S_FOCUSED_CONCUSSION, 1)]
  , iflavour = zipPlain [BrYellow]
  , icount   = 4  -- 24 in total vs 12, higher spread, less harm from pushing
  , irarity  = [(1, 1)]
  , iverbHit = "ignite"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toLinger 0  -- 0 steps, 1 turn
               , SetFlag Fragile, SetFlag Blast ]
  , ieffects = [OnSmash $ Explode S_CONCUSSION]
  , idesc    = idesc spreadConcussion
  , ikit     = []
  }
spreadFlash = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "magnesium flash"
  , ifreq    = [(S_VIOLENT_FLASH, 1)]
  , iflavour = zipPlain [BrWhite]
  , icount   = 13
  , irarity  = [(1, 1)]
  , iverbHit = "dazzle"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ ToThrow $ ThrowMod 100 20 4  -- 4 steps, 1 turn
               , SetFlag Fragile, SetFlag Blast
               , AddSkill SkShine 5 ]
  , ieffects = [ toOrganBad S_BLIND 5
               , toOrganBad S_WEAKENED 20 ]
                 -- Wikipedia says: blind for five seconds and afterimage
                 -- for much longer, harming aim
  , idesc    = "A very bright flash of fire, causing long-lasting afterimages."
  , ikit     = []
  }
spreadFlash8 = spreadFlash
  { iname    = "spark"
  , ifreq    = [(S_SPARK, 1)]
  , icount   = 5
  , iverbHit = "singe"
  , iaspects = [ ToThrow $ ThrowMod 100 10 2  -- 2 steps, 1 turn
               , SetFlag Fragile, SetFlag Blast
               , AddSkill SkShine 5 ]
  }
focusedFlash = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "magnesium ignition"
  , ifreq    = [(S_FOCUSED_FLASH, 1)]
  , iflavour = zipPlain [BrYellow]
  , icount   = 5  -- 25 in total vs 13, higher spread
  , irarity  = [(1, 1)]
  , iverbHit = "ignite"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toLinger 0  -- 0 steps, 1 turn
               , SetFlag Fragile, SetFlag Blast ]
  , ieffects = [OnSmash $ Explode S_SPARK]
  , idesc    = idesc spreadFlash
  , ikit     = []
  }
singleSpark = spreadFlash
  { iname    = "single spark"
  , ifreq    = [(S_SINGLE_SPARK, 1)]  -- too weak to start a fire
  , icount   = 1
  , iverbHit = "spark"
  , iaspects = [ toLinger 5  -- 1 step, 1 turn
               , SetFlag Fragile, SetFlag Blast
               , AddSkill SkShine 3 ]
  , ieffects = []
  , idesc    = "A glowing ember."
  , ikit     = []
  }
glassPiece = ItemKind
  { isymbol  = toContentSymbol '*'
  , iname    = "glass piece"
  , ifreq    = [(S_GLASS_HAIL, 1)]
  , iflavour = zipPlain [Blue]
  , icount   = 6
  , irarity  = [(1, 1)]
  , iverbHit = "cut"
  , iweight  = 1
  , idamage  = 2 `d` 1
  , iaspects = [ ToThrow $ ThrowMod 100 10 4  -- 2 steps, 1 turn
               , SetFlag Fragile, SetFlag Blast
               , AddSkill SkHurtMelee $ -15 * 5 ]
                 -- brittle, not too dense; armor blocks
  , ieffects = []
  , idesc    = "Swift, sharp edges."
  , ikit     = []
  }
focusedGlass = glassPiece  -- when blowing up windows
  { ifreq    = [(S_FOCUSED_GLASS_HAIL, 1)]
  , icount   = 2
  , iaspects = [ toLinger 0  -- 0 steps, 1 turn
               , SetFlag Fragile, SetFlag Blast
               , AddSkill SkHurtMelee $ -15 * 5 ]
  , ieffects = [OnSmash $ Explode S_GLASS_HAIL]
  }

-- * Assorted blasts that don't induce conditions or not used mainly for them

fragrance = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "fragrance"  -- instant, fast fragrance
  , ifreq    = [(S_FRAGRANCE, 1)]
  , iflavour = zipPlain [Magenta]
  , icount   = 8
  , irarity  = [(1, 1)]
  , iverbHit = "engulf"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ ToThrow $ ThrowMod 200 5 1  -- 2 steps, .5 turn (necklaces)
               , SetFlag Fragile, SetFlag Blast ]
  , ieffects = [Impress, toOrganGood S_ROSE_SMELLING 45]
  -- Linger 10, because sometimes it takes 2 turns due to starting just
  -- before actor turn's end (e.g., via a necklace).
  , idesc    = "A pleasant scent."
  , ikit     = []
  }
pheromone = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "musky whiff"  -- a kind of mist rather than fragrance
  , ifreq    = [(S_PHEROMONE, 1)]
  , iflavour = zipPlain [BrMagenta]
  , icount   = 16
  , irarity  = [(1, 1)]
  , iverbHit = "tempt"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toVelocity 10  -- 2 steps, 2 turns
               , SetFlag Fragile, SetFlag Blast ]
  , ieffects = [Dominate]
  , idesc    = "A sharp, strong scent."
  , ikit     = []
  }
mistCalming = ItemKind  -- unused
  { isymbol  = toContentSymbol '`'
  , iname    = "mist"
  , ifreq    = [(S_CALMING_MIST, 1)]
  , iflavour = zipPlain [BrGreen]
  , icount   = 8
  , irarity  = [(1, 1)]
  , iverbHit = "sooth"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toVelocity 5  -- 1 step, 1 turn
               , SetFlag Fragile, SetFlag Blast ]
  , ieffects = [RefillCalm 2]
  , idesc    = "A soothing, gentle cloud."
  , ikit     = []
  }
odorDistressing = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "distressing whiff"
  , ifreq    = [(S_DISTRESSING_ODOR, 1)]
  , iflavour = zipFancy [BrRed]  -- salmon
  , icount   = 8
  , irarity  = [(1, 1)]
  , iverbHit = "distress"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toLinger 10  -- 2 steps, 1 turn
               , SetFlag Fragile, SetFlag Blast ]
  , ieffects = [ RefillCalm (-10)
               , toOrganBad S_FOUL_SMELLING (20 + 1 `d` 5)
               , toOrganBad S_IMPATIENT (2 + 1 `d` 2) ]
  , idesc    = "It turns the stomach."  -- and so can't stand still
  , ikit     = []
  }
mistHealing = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "mist"  -- powerful, so slow and narrow
  , ifreq    = [(S_HEALING_MIST, 1)]
  , iflavour = zipFancy [BrGreen]
  , icount   = 8
  , irarity  = [(1, 1)]
  , iverbHit = "revitalize"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toVelocity 5  -- 1 step, 1 turn
               , SetFlag Fragile, SetFlag Blast
               , AddSkill SkShine 1 ]
  , ieffects = [RefillHP 2]
  , idesc    = "It fills the air with light and life."
  , ikit     = []
  }
mistHealing2 = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "mist"
  , ifreq    = [(S_HEALING_MIST_2, 1)]
  , iflavour = zipPlain [Green]
  , icount   = 8
  , irarity  = [(1, 1)]
  , iverbHit = "revitalize"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toVelocity 5  -- 1 step, 1 turn
               , SetFlag Fragile, SetFlag Blast
               , AddSkill SkShine 2 ]
  , ieffects = [RefillHP 4]
  , idesc    = "At its touch, wounds close and bruises fade."
  , ikit     = []
  }
mistWounding = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "mist"
  , ifreq    = [(S_WOUNDING_MIST, 1)]
  , iflavour = zipPlain [BrRed]
  , icount   = 8
  , irarity  = [(1, 1)]
  , iverbHit = "devitalize"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toVelocity 5  -- 1 step, 1 turn
               , SetFlag Fragile, SetFlag Blast ]
  , ieffects = [RefillHP (-2)]
  , idesc    = "The air itself stings and itches."
  , ikit     = []
  }
distortion = ItemKind
  { isymbol  = toContentSymbol 'v'
  , iname    = "vortex"
  , ifreq    = [(S_DISTORTION, 1)]
  , iflavour = zipPlain [White]
  , icount   = 8  -- braced are immune to Teleport; avoid failure messages
  , irarity  = [(1, 1)]
  , iverbHit = "engulf"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toLinger 10  -- 2 steps, 1 turn
               , SetFlag Lobable, SetFlag Fragile, SetFlag Blast ]
  , ieffects = [Teleport $ 15 + 1 `d` 10]
  , idesc    = "The air shifts oddly, as though light is being warped."
  , ikit     = []
  }
smoke = ItemKind  -- when stuff burns out  -- unused
  { isymbol  = toContentSymbol '`'
  , iname    = "smoke fume"  -- pluralizes better than 'smokes'
  , ifreq    = [(S_SMOKE, 1)]
  , iflavour = zipPlain [BrBlack]
  , icount   = 16
  , irarity  = [(1, 1)]
  , iverbHit = "choke"  -- or "obscure"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toVelocity 20  -- 4 steps, 2 turns
               , SetFlag Fragile, SetFlag Blast ]
  , ieffects = [toOrganBad S_WITHHOLDING (5 + 1 `d` 3)]
                  -- choking and tears, can roughly see, but not aim
  , idesc    = "Twirling clouds of grey smoke."
  , ikit     = []
  }
boilingWater = ItemKind
  { isymbol  = toContentSymbol '*'
  , iname    = "boiling water"
  , ifreq    = [(S_BOILING_WATER, 1)]
  , iflavour = zipPlain [White]
  , icount   = 17  -- 18 causes 3 particles to hit the same actor 3 tiles away
  , irarity  = [(1, 1)]
  , iverbHit = "boil"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toVelocity 30  -- 6 steps, 2 turns
               , SetFlag Fragile, SetFlag Blast ]
  , ieffects = [Burn 1]
  , idesc    = "It bubbles and hisses."
  , ikit     = []
  }
glue = ItemKind
  { isymbol  = toContentSymbol '*'
  , iname    = "hoof glue"
  , ifreq    = [(S_GLUE, 1)]
  , iflavour = zipPlain [Cyan]
  , icount   = 8  -- Paralyze doesn't stack; avoid failure messages
  , irarity  = [(1, 1)]
  , iverbHit = "glue"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toVelocity 10  -- 2 steps, 2 turns
               , SetFlag Fragile, SetFlag Blast ]
  , ieffects = [Paralyze 10]
  , idesc    = "Thick and clinging."
  , ikit     = []
  }
waste = ItemKind
  { isymbol  = toContentSymbol '*'
  , iname    = "waste piece"
  , ifreq    = [(S_WASTE, 1)]
  , iflavour = zipPlain [Brown]
  , icount   = 16
  , irarity  = [(1, 1)]
  , iverbHit = "splosh"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [toLinger 10, SetFlag Fragile, SetFlag Blast]
  , ieffects = [ toOrganBad S_FOUL_SMELLING (30 + 1 `d` 10)
               , toOrganBad S_DISPOSSESSED (10 + 1 `d` 5) ]
  , idesc    = "Sodden and foul-smelling."
  , ikit     = []
  }
mistAntiSlow = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "mist"
  , ifreq    = [(S_ANTI_SLOW_MIST, 1)]
  , iflavour = zipFancy [BrYellow]
  , icount   = 8
  , irarity  = [(1, 1)]
  , iverbHit = "propel"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toVelocity 5  -- 1 step, 1 turn
               , SetFlag Fragile, SetFlag Blast ]
  , ieffects = [DropItem 1 1 COrgan S_SLOWED]
  , idesc    = "A cleansing rain."
  , ikit     = []
  }
mistAntidote = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "mist"
  , ifreq    = [(S_ANTIDOTE_MIST, 1)]
  , iflavour = zipFancy [BrBlue]
  , icount   = 8
  , irarity  = [(1, 1)]
  , iverbHit = "cure"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toVelocity 5  -- 1 step, 1 turn
               , SetFlag Fragile, SetFlag Blast ]
  , ieffects = [DropItem 1 maxBound COrgan S_POISONED]
  , idesc    = "Washes away death's dew."
  , ikit     = []
  }
mistSleep = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "mist"
  , ifreq    = [(S_SLEEP_MIST, 1)]
  , iflavour = zipFancy [BrMagenta]
  , icount   = 8
  , irarity  = [(1, 1)]
  , iverbHit = "put to sleep"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toVelocity 5  -- 1 step, 1 turn
               , SetFlag Fragile, SetFlag Blast ]
  , ieffects = [PutToSleep]
  , idesc    = "Lulls weary warriors."
  , ikit     = []
  }

-- * Condition-inducing blasts

-- Almost all have @toLinger 10@, that travels 2 steps in 1 turn.
-- These are very fast projectiles, not getting into the way of big
-- actors and not burdening the engine for long.
-- A few are slower 'mists'.

denseShower = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "dense shower"
  , ifreq    = [(S_DENSE_SHOWER, 1)]
  , iflavour = zipFancy [Green]
  , icount   = 12
  , irarity  = [(1, 1)]
  , iverbHit = "strengthen"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [toLinger 10, SetFlag Fragile, SetFlag Blast]
  , ieffects = [toOrganGood S_STRENGTHENED 5]
  , idesc    = "A thick rain of droplets."
  , ikit     = []
  }
sparseShower = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "sparse shower"
  , ifreq    = [(S_SPARSE_SHOWER, 1)]
  , iflavour = zipFancy [Red]
  , icount   = 8
  , irarity  = [(1, 1)]
  , iverbHit = "weaken"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [toLinger 10, SetFlag Fragile, SetFlag Blast]
  , ieffects = [toOrganBad S_WEAKENED 7]
  , idesc    = "Light droplets that cling to clothing."
  , ikit     = []
  }
protectingBalmMelee = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "balm droplet"
  , ifreq    = [(S_MELEE_PROTECTIVE_BALM, 1)]
  , iflavour = zipFancy [Brown]
  , icount   = 6
  , irarity  = [(1, 1)]
  , iverbHit = "balm"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toLinger 0  -- 0 steps, 1 turn
               , SetFlag Fragile, SetFlag Blast ]
  , ieffects = [toOrganGood S_PROTECTED_FROM_MELEE (3 + 1 `d` 3)]
  , idesc    = "A thick ointment that hardens the skin."
  , ikit     = []
  }
protectingBalmRanged = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "balm droplet"
  , ifreq    = [(S_RANGE_PROTECTIVE_BALM, 1)]
  , iflavour = zipPlain [BrYellow]
  , icount   = 16
  , irarity  = [(1, 1)]
  , iverbHit = "balm"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [toLinger 10, SetFlag Fragile, SetFlag Blast]
  , ieffects = [toOrganGood S_PROTECTED_FROM_RANGED (3 + 1 `d` 3)]
  , idesc    = "Grease that protects from flying death."
  , ikit     = []
  }
defenselessnessRunout = ItemKind
  { isymbol  = toContentSymbol '?'
  , iname    = "PhD defense question"
  , ifreq    = [(S_DEFENSELESSNESS_RUNOUT, 1)]
  , iflavour = zipFancy [BrRed]
  , icount   = 16
  , irarity  = [(1, 1)]
  , iverbHit = "nag"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [toLinger 10, SetFlag Fragile, SetFlag Blast]
  , ieffects = [toOrganBad S_DEFENSELESS (3 + 1 `d` 3)]
  , idesc    = "Only the most learned make use of this."
  , ikit     = []
  }
resolutionDust = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "resolution dust"
  , ifreq    = [(S_RESOLUTION_DUST, 1)]
  , iflavour = zipPlain [Brown]
  , icount   = 16
  , irarity  = [(1, 1)]
  , iverbHit = "calm"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [toLinger 10, SetFlag Fragile, SetFlag Blast]
  , ieffects = [toOrganGood S_RESOLUTE (3 + 1 `d` 3)]
                 -- short enough duration that @calmEnough@ not a big problem
  , idesc    = "A handful of honest earth, to strengthen the soul."
  , ikit     = []
  }
hasteSpray = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "haste spray"
  , ifreq    = [(S_HASTE_SPRAY, 1)]
  , iflavour = zipFancy [BrYellow]
  , icount   = 16
  , irarity  = [(1, 1)]
  , iverbHit = "haste"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [toLinger 10, SetFlag Fragile, SetFlag Blast]
  , ieffects = [toOrganGood S_HASTED (3 + 1 `d` 3)]
  , idesc    = "A quick spurt."
  , ikit     = []
  }
spreadNitrogen = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "slowness mist"
  , ifreq    = [(S_VIOLENT_SLOWNESS_MIST, 1)]
  , iflavour = zipPlain [BrBlack]
  , icount   = 15
  , irarity  = [(1, 1)]
  , iverbHit = "freeze"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toVelocity 10  -- 2 steps, 2 turns, mist, slow
               , SetFlag Fragile, SetFlag Blast ]
  , ieffects = [toOrganBad S_SLOWED (2 + 1 `d` 3)]
  , idesc    = "Colourless cold clammy fog, making each movement an effort."
  , ikit     = []
  }
spreadNitrogen8 = spreadNitrogen
  { ifreq    = [(S_SLOWNESS_MIST, 1)]
  , icount   = 7
  , iaspects = [ toVelocity 5  -- 1 step, 1 turn, mist, slow
               , SetFlag Fragile, SetFlag Blast ]
  }
focusedNitrogen = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "slowness mist droplet"
  , ifreq    = [(S_FOCUSED_SLOWNESS_MIST, 1)]
  , iflavour = zipFancy [White]
  , icount   = 4 -- 28 in total vs 15, higher spread
  , irarity  = [(1, 1)]
  , iverbHit = "freeze"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toLinger 0  -- 0 steps, 1 turn
               , SetFlag Fragile, SetFlag Blast ]
  , ieffects = [ OnSmash $ Explode S_SLOWNESS_MIST
               , toOrganBad S_SLOWED (2 + 1 `d` 3) ]
  , idesc    = "Colourless and colder than ice."
  , ikit     = []
  }
eyeDrop = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "eye drop"
  , ifreq    = [(S_EYE_DROP, 1)]
  , iflavour = zipFancy [BrCyan]
  , icount   = 16
  , irarity  = [(1, 1)]
  , iverbHit = "cleanse"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [toLinger 10, SetFlag Fragile, SetFlag Blast]
  , ieffects = [toOrganGood S_FAR_SIGHTED (3 + 1 `d` 3)]
  , idesc    = "Not to be taken orally."
  , ikit     = []
  }
ironFiling = ItemKind  -- fast, short, strongly blinding blast
  { isymbol  = toContentSymbol '`'
  , iname    = "iron filing"
  , ifreq    = [(S_IRON_FILING, 1)]
  , iflavour = zipPlain [Red]
  , icount   = 16
  , irarity  = [(1, 1)]
  , iverbHit = "blind"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [toLinger 10, SetFlag Fragile, SetFlag Blast]
  , ieffects = [toOrganBad S_BLIND (10 + 1 `d` 10)]
  , idesc    = "A shaving of bright metal."
  , ikit     = []
  }
smellyDroplet = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "smelly droplet"
  , ifreq    = [(S_SMELLY_DROPLET, 1)]
  , iflavour = zipFancy [Blue]
  , icount   = 16
  , irarity  = [(1, 1)]
  , iverbHit = "sensitize"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [toLinger 10, SetFlag Fragile, SetFlag Blast]
  , ieffects = [toOrganGood S_KEEN_SMELLING (5 + 1 `d` 3)]
  , idesc    = "A viscous lump that stains the skin."
  , ikit     = []
  }
eyeShine = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "eye shine"
  , ifreq    = [(S_EYE_SHINE, 1)]
  , iflavour = zipFancy [Cyan]
  , icount   = 16
  , irarity  = [(1, 1)]
  , iverbHit = "smear"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [toLinger 10, SetFlag Fragile, SetFlag Blast]
  , ieffects = [toOrganGood S_SHINY_EYED (3 + 1 `d` 3)]
  , idesc    = "They almost glow in the dark."
  , ikit     = []
  }
whiskeySpray = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "whiskey spray"
  , ifreq    = [(S_WHISKEY_SPRAY, 1)]
  , iflavour = zipFancy [Brown]
  , icount   = 16
  , irarity  = [(1, 1)]
  , iverbHit = "inebriate"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [toLinger 10, SetFlag Fragile, SetFlag Blast]
  , ieffects = [toOrganGood S_DRUNK (3 + 1 `d` 3)]
  , idesc    = "It burns in the best way."
  , ikit     = []
  }
youthSprinkle = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "youth sprinkle"
  , ifreq    = [(S_YOUTH_SPRINKLE, 1)]
  , iflavour = zipFancy [BrGreen]
  , icount   = 16
  , irarity  = [(1, 1)]
  , iverbHit = "sprinkle"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [toLinger 10, SetFlag Fragile, SetFlag Blast]
  , ieffects = [ toOrganGood S_ROSE_SMELLING (40 + 1 `d` 20)
               , toOrganNoTimer S_REGENERATING ]
  , idesc    = "Bright and smelling of the Spring."
  , ikit     = []
  }
poisonCloud = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "poison cloud"
  , ifreq    = [(S_POISON_CLOUD, 1)]
  , iflavour = zipFancy [BrMagenta]
  , icount   = 11  -- low, to be less deadly in a tunnel, compared to single hit
  , irarity  = [(1, 1)]
  , iverbHit = "poison"
  , iweight  = 0  -- lingers, blocking path
  , idamage  = 0
  , iaspects = [ ToThrow $ ThrowMod 10 100 2  -- 2 steps, 2 turns
               , SetFlag Fragile, SetFlag Blast ]
  , ieffects = [toOrganNoTimer S_POISONED]
  , idesc    = "Choking gas that stings the eyes."
  , ikit     = []
  }
pingFlash = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "flash"
  , ifreq    = [(S_PING_PLASH, 1)]
  , iflavour = zipFancy [Green]
  , icount   = 1
  , irarity  = [(1, 1)]
  , iverbHit = "ping"
  , iweight  = 1  -- to prevent blocking the way
  , idamage  = 0
  , iaspects = [ ToThrow $ ThrowMod 200 0 1  -- 1 step, .5 turn (necklaces)
               , SetFlag Fragile, SetFlag Blast
               , AddSkill SkShine 2 ]
  , ieffects = [OnSmash Yell]
  , idesc    = "A ping and a display flash from an echolocator out of sync momentarily."
  , ikit     = []
  }
blastNoStat :: GroupName ItemKind -> ItemKind
blastNoStat grp = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "mist"
  , ifreq    = [(blastNoStatOf grp, 1)]
  , iflavour = zipFancy [White]
  , icount   = 12
  , irarity  = [(1, 1)]
  , iverbHit = "drain"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toVelocity 10  -- 2 steps, 2 turns
               , SetFlag Fragile, SetFlag Blast ]
  , ieffects = [toOrganBad grp (3 + 1 `d` 3)]
  , idesc    = "Completely disables one personal faculty."
  , ikit     = []
  }
blastNoSkMove = blastNoStat S_IMMOBILE
blastNoSkMelee = blastNoStat S_PACIFIED
blastNoSkDisplace = blastNoStat S_IRREPLACEABLE
blastNoSkAlter = blastNoStat S_RETAINING
blastNoSkWait = blastNoStat S_IMPATIENT
blastNoSkMoveItem = blastNoStat S_DISPOSSESSED
blastNoSkProject = blastNoStat S_WITHHOLDING
blastNoSkApply = blastNoStat S_PARSIMONIOUS
blastBonusStat :: GroupName ItemKind -> ItemKind
blastBonusStat grp = ItemKind
  { isymbol  = toContentSymbol '`'
  , iname    = "dew"
  , ifreq    = [(blastBonusStatOf grp, 1)]
  , iflavour = zipFancy [White]
  , icount   = 12
  , irarity  = [(1, 1)]
  , iverbHit = "elevate"
  , iweight  = 1
  , idamage  = 0
  , iaspects = [ toVelocity 10  -- 2 steps, 2 turns
               , SetFlag Fragile, SetFlag Blast ]
  , ieffects = [toOrganGood grp (20 + 1 `d` 5)]
  , idesc    = "Temporarily enhances the given personal faculty."
  , ikit     = []
  }
blastBonusSkMove = blastBonusStat S_MORE_MOBILE
blastBonusSkMelee = blastBonusStat S_MORE_COMBATIVE
blastBonusSkDisplace = blastBonusStat S_MORE_DISPLACING
blastBonusSkAlter = blastBonusStat S_MORE_MODIFYING
blastBonusSkWait = blastBonusStat S_MORE_PATIENT
blastBonusSkMoveItem = blastBonusStat S_MORE_TIDY
blastBonusSkProject = blastBonusStat S_MORE_PROJECTING
blastBonusSkApply = blastBonusStat S_MORE_PRACTICAL
