102 lines
3.4 KiB
Haskell
102 lines
3.4 KiB
Haskell
module Dodge.Item.Weapon.Grenade
|
|
where
|
|
import Dodge.Data
|
|
import Dodge.Data.SoundOrigin
|
|
import Dodge.Item.Data
|
|
import Dodge.Base
|
|
import Dodge.Zone
|
|
import Dodge.SoundLogic
|
|
import Dodge.SoundLogic.LoadSound
|
|
import Dodge.Item.Attachment.Data
|
|
import Dodge.Item.Draw
|
|
import Picture
|
|
import Geometry
|
|
import ShapePicture
|
|
import Shape
|
|
|
|
import Control.Lens
|
|
import qualified Data.IntMap.Strict as IM
|
|
|
|
moveGrenade :: Prop -> World -> World
|
|
moveGrenade pj w
|
|
| _pjTimer pj <= 0 = w
|
|
& props %~ IM.delete pID
|
|
& _pjPayload pj (_pjPos (_props w IM.! pID))
|
|
| otherwise = case collideCircWalls oldPos newPos 4 $ wallsNearPoint newPos w of
|
|
Nothing -> w & props . ix pID %~ normalUpdate
|
|
Just (p,v) -> w
|
|
& soundStart (Tap 0) p tapQuietS Nothing
|
|
& props . ix pID %~ ( ( pjPos .~ p ) . ( pjTimer -~ 1 ) . (pjVel .~ v) )
|
|
where
|
|
pID = _pjID pj
|
|
normalUpdate = (pjTimer -~ 1)
|
|
. (pjZ %~ (max 0 . (+ _pjVelZ pj)))
|
|
. (pjVelZ -~ 0.1)
|
|
. ( pjPos .~ newPos )
|
|
oldPos = _pjPos pj
|
|
newPos = _pjVel pj +.+ oldPos
|
|
|
|
grenadePic :: Int -> SPic
|
|
grenadePic time =
|
|
( colorSH (dark $ dark green) $ upperPrismPolyHalf 5 $ polyCirc 3 5
|
|
, pictures
|
|
[ color green $ arc (degToRad $ (179 * fromIntegral time / 50) - 180 )
|
|
(degToRad $ 180 - (179 * fromIntegral time / 50) )
|
|
5
|
|
-- , translate (-2) 2 $ rotate (pi*0.5)
|
|
-- $ scale 0.05 0.05 $ color green $ text $ show $ 1 + quot time 20
|
|
]
|
|
)
|
|
|
|
grenadeDraw :: Float -> Prop -> SPic
|
|
grenadeDraw dir prop = translateSPz z $ uncurryV translateSPf p $ rotateSP dir $ grenadePic time
|
|
where
|
|
p = _pjPos prop
|
|
time = _pjTimer prop
|
|
z = _pjZ prop
|
|
|
|
throwGrenade
|
|
:: (Point2 -> World -> World) -- ^ Payload
|
|
-> Creature
|
|
-> World
|
|
-> World
|
|
throwGrenade thePayload cr w = setWp $ removePict $ over props addG w
|
|
where
|
|
n = _crID cr
|
|
addG = IM.insert i $ Bomb
|
|
{ _pjPos = p
|
|
, _pjZ = 10
|
|
, _pjVelZ = 2
|
|
, _pjVel = v
|
|
, _prDraw = grenadeDraw dir
|
|
, _pjID = i
|
|
, _pjUpdate = moveGrenade
|
|
, _pjPayload = thePayload
|
|
, _pjTimer = fuseTime
|
|
}
|
|
j = _crInvSel cr
|
|
removePict = set (creatures . ix n . crInv . ix j . itEquipPict) $ \ _ _ -> (,) emptySH 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
|