{-| Module : Unit.Smart.STank Description : Super tank Copyright : (c) Christopher Howard, 2016 License : GPL-3 Maintainer : ch.howard@zoho.com -} module Unit.Smart.STank ( STank(..) , new ) where import Prelude ((.), Maybe(..), max, (-), pi, 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 ( Moving(..), Locatable(..), Colliding(..), newVelocity, newLocation ) import Combat import qualified Projectile.BulletMII as P.BulletMII ( prj ) import AfterEffect ( AfterEffect(AfterEffect) ) import qualified AfterEffect.SimpleExplosion as SimpleExplosion ( new ) import Universe ( Arena ) import qualified Universe as U () import Common import UnitUtil import Unit radialVelocity = pi/4 maxVelocityMag = 100 kamikazeDamage = 20 maxIntegrity = 6 accelerationRate = 60 collisionR = 45 shotDelay = 2 data STank = STank { angle :: Angle -- radians , velocity :: Velocity , center :: WP , wmap :: WM , launchTube :: [Projectile] , sinceLastShot :: Time , integrity :: Double , vision :: Maybe Arena , rt :: ResourceTracker , queueShotSnd :: Bool , shotSndSrc :: Maybe Source } instance Audible STank 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 :: ResourceTracker -> WM -> WP -> Angle -> STank new a b c d = STank { center = c , angle = d , velocity = (0.0, 0.0) , wmap = b , launchTube = [] , sinceLastShot = 0.0 , integrity = maxIntegrity , vision = Nothing , rt = a , queueShotSnd = False , shotSndSrc = Nothing } instance Observant STank where updateVision s a = s { vision = Just a } updateAngle t s = adjAngle s t vision (\x y -> x { angle = y }) angle (pi / 6) radialVelocity updateVelocity t s = s { velocity = M.newVelocity (velocity s) accelerationRate (angle s) maxVelocityMag t } instance Animation STank where image s _ = reorient (angle s) (protectedGetImage (rt s) "stank.bmp") instance M.Locatable STank where center = center instance M.Moving STank where velocity = velocity instance M.Colliding STank where collisionRadius _ = collisionR instance InternallyUpdating STank where preUpdate s t = (updateFiringInformation t . updateVelocity t . updateAngle t) s postUpdate s t = s { center = M.newLocation (wmap s) (center s) (velocity s) t } updateFiringInformation t s = firing s sinceLastShot shotDelay (\x y -> x { sinceLastShot = y }) (\x y -> x { launchTube = y }) (\x y -> x { queueShotSnd = y }) q t launchTube where p = P.BulletMII.prj s wmap q = map p [ r, r + pi / 8, r - pi / 8 ] r = firingAngle s vision angle instance Launcher STank where deployProjectiles s = (launchTube s, s { launchTube = [] }) instance Transient STank where expired' s = if moreThanZero (integrity s) then Nothing else Just [a] where a = AfterEffect (SimpleExplosion.new (rt s)(wmap s) (center s) (velocity s)) instance Damageable STank where inflictDamage s d = s { integrity = max 0 (integrity s - d) } instance Damaging STank where damageEnergy s = kamikazeDamage