Files
loop/src/Dodge/Item/Weapon/Grenade.hs
T
2021-09-09 14:58:07 +01:00

105 lines
3.7 KiB
Haskell

module Dodge.Item.Weapon.Grenade
where
import Dodge.Data
import Dodge.Item.Data
import Dodge.Base
import Dodge.Base.Zone
import Dodge.Picture.Layer
import Dodge.SoundLogic
import Dodge.SoundLogic.Synonyms
import Dodge.Item.Attachment.Data
import Dodge.Item.Draw
import Dodge.Default.Shell
--import Dodge.Default
import Picture
import Geometry
import Control.Lens
import qualified Data.IntMap.Strict as IM
--import System.Random
moveGrenade
:: Int -- ^ Timer
-> Float -- ^ Direction
-> Int -- ^ Projectile id
-> World
-> World
moveGrenade 0 _ pID w = over projectiles (IM.delete pID)
$ explosion (_pjPos (_projectiles w IM.! pID))
w
where
pj = _projectiles w IM.! pID
explosion = _pjPayload pj
moveGrenade time dir pID w = case hitWl of
Just (p,_) -> soundFrom (Tap 0) p tapQuiet Nothing updatedWorld
_ -> updatedWorld
where
updatedWorld = updateV $ set (projectiles . ix pID . pjPos) finalPos
$ set (projectiles .ix pID. pjDraw)
(\ _ -> onLayer PtLayer $ uncurryV translate newPos
$ rotate dir $ grenadePic time)
$ set (projectiles .ix pID.pjUpdate) (\_ -> moveGrenade (time-1) dir pID) w
pj = _projectiles w IM.! pID
oldPos = _pjPos pj
newPos = _pjVel pj +.+ oldPos
hitWl = collideCircWalls oldPos newPos 4 $ wallsNearPoint newPos w
finalPos = maybe newPos fst hitWl
setV v = set (projectiles .ix pID.pjVel) v
updateV = maybe id (setV . snd) hitWl
grenadePic :: Int -> Picture
grenadePic x = pictures
[ color (dark $ dark green) $ circleSolid 5
, color green $ arc (degToRad $ (179 * fromIntegral x / 50) - 180 )
(degToRad $ 180 - (179 * fromIntegral x / 50) )
5
, translate (-2) 2 $ rotate (pi*0.5)
$ scale 0.05 0.05 $ color green $ text $ show $ 1 + quot x 20
]
throwGrenade
:: (Point2 -> World -> World) -- ^ Payload
-> Creature
-> World
-> World
throwGrenade explosion cr w = setWp $ removePict $ over projectiles addG w
where
n = _crID cr
addG = IM.insert i $ defaultShell
{ _pjPos = p
, _pjStartPos = p
, _pjVel = v
, _pjDraw = \_ -> onLayer PtLayer $ uncurryV translate p $ grenadePic 0
, _pjID = i
, _pjUpdate = \_ -> moveGrenade fuseTime dir i
, _pjPayload = explosion
}
j = _crInvSel cr
removePict = set (creatures . ix n . crInv . ix j . itEquipPict) $ \ _ _ -> blank
i = newProjectileKey w
--(_, g) = randomR (-grenadeAccA,grenadeAccA::Float) (_randGen w)
--(_, _) = randomR (1 - 2*grenadeAccL,1+grenadeAccL::Float) g
v' = 1 / (fromIntegral fuseTime * _cameraZoom w) *.* rotateV (_cameraRot w) ( _mousePos w)
v | magV v' > 6 = 6 *.* normalizeV v'
| otherwise = v'
p' = _crPos cr +.+ rotateV (_crDir cr) (V2 (_crRad cr) 0)
p | circOnSomeWall p' 4 w = _crPos cr +.+ rotateV (_crDir cr) (V2 (_crRad cr-4) 0)
| otherwise = p'
dir = argV v
setWp :: World -> World
setWp w' = w' & creatures . ix n . crInv . ix j . itEffect .~ throwArmReset 20
fuseTime = _itFuseTime $ _itAttachment $ _crInv cr IM.! j
throwArmReset :: Int -> ItEffect
throwArmReset x = ItInvEffect {_itInvEffect = f ,_itEffectCounter = x }
where
f _ cr i = creatures . ix (_crID cr) . crInv %~ IM.adjust counterDown i
counterDown it
| _itEffectCounter (_itEffect it) == 0 = it
& itHammer .~ HammerUp
& itEquipPict .~ pictureWeaponOnAim (grenadePic 50)
| otherwise = it & itEffect . itEffectCounter -~ 1
--(grenadeAccL, grenadeAccA) = (0.1, 0.1)