{-| Module : Unit.Simple.Turret Description : Fixed gun turret which rotates while firing Copyright : (c) Christopher Howard, 2016 License : GPL-3 Maintainer : ch.howard@zoho.com -} module Unit.Simple.Turret ( Turret(..) , new ) where import Prelude ((+), (>), Maybe(..), max, (-), (/), pi, (*), sin, cos, Bool(..), (.), Double, map) import Data.WrapAround (WP, WM) import Sound.ALUT (Source(..)) import Animation import Math import ResourceTracker import Updating import qualified Moving as M (Locatable(..), Moving(..), Colliding(..), newLocation') import Combat import qualified Projectile.BulletSI as P.BulletSI (prj) import AfterEffect import qualified AfterEffect.SimpleExplosion as SimpleExplosion (new) import Common import Unit radVelocity = pi/6 -- radians per second velMagnitude = 40 kamikazeDmg = 6.0 maxInteg = 2.0 cRadius = 16 data Turret = Turret { tAngle :: Angle , velocity :: Velocity , center :: WP , wmap :: WM , launchTube :: [Projectile] , sinceLastShot :: Time , integrity :: Double , rt :: RT , queueShotSnd :: Bool , shotSndSrc :: Maybe Source } instance Audible Turret where processAudio s a = handSndSrc s queueShotSnd shotSndSrc (\a -> a { queueShotSnd = False }) rt "energy-shot-02.wav" (\a b -> a { shotSndSrc = Just b }) a (wmap s) (M.center) terminateAudio s = termSndSrc s shotSndSrc new a b c d e = Turret { center = c , tAngle = d , velocity = appPair (* velMagnitude) (sin e, cos e) , wmap = b , launchTube = [] , sinceLastShot = 0 , integrity = maxInteg , rt = a , queueShotSnd = False , shotSndSrc = Nothing } updateAngle t s = s { tAngle = tAngle s - radVelocity * t} instance Animation Turret where image s _ = reorient (tAngle s) (protectedGetImage (rt s) "turret.bmp") instance M.Locatable Turret where center = center instance M.Moving Turret where velocity = velocity instance M.Colliding Turret where collisionRadius _ = cRadius instance InternallyUpdating Turret where preUpdate s t = (updateFiringInformation t . updateAngle t) s postUpdate s t = s { center = M.newLocation' s (wmap s) t } updateFiringInformation t s = firing s sinceLastShot 1.5 (\x y -> x { sinceLastShot = y }) (\x y -> x { launchTube = y }) (\x y -> x { queueShotSnd = y }) p t launchTube where p = map f [ 0.0, pi / 2, pi, 3 * pi / 2 ] f x = P.BulletSI.prj s wmap (tAngle s + x) instance Launcher Turret where deployProjectiles s = (launchTube s, s { launchTube = [] }) instance Transient Turret where expired' s = if integrity s > 0 then Nothing else Just [a] where a = AfterEffect (SimpleExplosion.new (rt s) (wmap s) (center s) (velocity s)) instance Damageable Turret where inflictDamage s d = s { integrity = max 0 (integrity s - d) } instance Damaging Turret where damageEnergy s = kamikazeDmg