155 lines
5.3 KiB
Haskell
155 lines
5.3 KiB
Haskell
{-# OPTIONS_GHC -Wno-unused-imports #-}
|
|
|
|
module Dodge.Projectile.Update where
|
|
|
|
import Control.Lens
|
|
import qualified Data.Map.Strict as M
|
|
import Data.Maybe
|
|
import Dodge.Base
|
|
import Dodge.Data.World
|
|
import Dodge.Default.Weapon
|
|
import Dodge.EnergyBall
|
|
import Dodge.Item.Location
|
|
import Dodge.Item.Weapon.Launcher
|
|
import Dodge.Item.Weapon.Remote
|
|
import Dodge.Item.Weapon.Shell
|
|
import Dodge.Item.Weapon.TriggerType
|
|
import Dodge.Movement.Turn
|
|
import Dodge.Payload
|
|
import Dodge.Reloading.Action
|
|
import Dodge.SoundLogic
|
|
import Dodge.SoundLogic.LoadSound
|
|
import Dodge.WorldEvent.Cloud
|
|
import Geometry
|
|
import qualified IntMapHelp as IM
|
|
import RandomHelp
|
|
import qualified SDL
|
|
import qualified Streaming.Prelude as S
|
|
|
|
updateProjectile :: Proj -> World -> World
|
|
updateProjectile pj = case pj of
|
|
Shell{} -> upsProjectile pj
|
|
|
|
shellCollisionCheck :: (Proj -> World -> World) -> Proj -> World -> World
|
|
shellCollisionCheck doExplode pj w
|
|
| time > 330 && circOnSomeWall oldPos 4 w = doExplode pj w
|
|
| time <= 330 && anythingHitCirc 2 oldPos newPos w = doExplode pj w
|
|
| time <= 0 = doExplode pj w
|
|
| otherwise = w
|
|
where
|
|
time = _prjTimer pj
|
|
oldPos = _prjPos pj
|
|
vel = _prjVel pj
|
|
newPos = oldPos +.+ vel
|
|
|
|
remoteShellCollisionCheck :: Proj -> World -> World
|
|
remoteShellCollisionCheck = shellCollisionCheck $ \pj -> explodeRemoteRocket (fromJust (_prjMITID pj)) (_prjID pj)
|
|
|
|
plainShellCollisionCheck :: Proj -> World -> World
|
|
plainShellCollisionCheck = shellCollisionCheck $ \pj ->
|
|
usePayload (_prjPayload pj) (_prjPos pj)
|
|
. stopSoundFrom (ShellSound (_prjID pj))
|
|
. (cWorld . projectiles %~ IM.delete (_prjID pj))
|
|
|
|
upsProjectile :: Proj -> World -> World
|
|
upsProjectile pj w' = foldr (`upProjectile` pj) w' (_prjUpdates pj)
|
|
|
|
upProjectile :: ProjectileUpdate -> Proj -> World -> World
|
|
upProjectile pu pj = case pu of
|
|
PJRemoteShellCollisionCheck -> remoteShellCollisionCheck pj
|
|
PJShellCollisionCheck -> plainShellCollisionCheck pj
|
|
PJDecTimMvVel -> decTimMvVel pj
|
|
PJThrust st et
|
|
| act st et -> doThrust pj
|
|
| otherwise -> id
|
|
PJSpin t cid spinamount
|
|
| ain t -> trySpinByCID cid spinamount pj
|
|
| otherwise -> id
|
|
PJTrack st et itid
|
|
| act st et -> pjTrack itid pj
|
|
| otherwise -> id
|
|
PJReduceSpin x -> reduceSpinBy x pj
|
|
PJRemoteDirection st et cid itid
|
|
| act st et -> setRemoteDir cid itid pj
|
|
| otherwise -> id
|
|
PJSetScope itid -> setRemoteScope itid (_prjPos pj)
|
|
PJRetireRemote itid 0 pjid -> retireRemoteProj itid pjid
|
|
PJRetireRemote _ _ pjid -> cWorld . projectiles . ix pjid . prjUpdates . ix 0 . pjuTimer -~ 1
|
|
where
|
|
time = _prjTimer pj
|
|
act st et = time <= st && time >= et
|
|
ain t = time == t
|
|
|
|
retireRemoteProj :: Int -> Int -> World -> World
|
|
retireRemoteProj itid pjid w =
|
|
w
|
|
& pointerToItemLocation (_itemLocations (_cWorld w) IM.! itid)
|
|
%~ ( (itScope . scopePos .~ V2 0 0)
|
|
. (itUse . heldUse .~ HeldFireRemoteShell)
|
|
)
|
|
& cWorld . props %~ IM.delete pjid
|
|
|
|
setRemoteDir :: Int -> Int -> Proj -> World -> World
|
|
setRemoteDir cid itid pj w = w & cWorld . projectiles . ix (_prjID pj) . prjAcc .~ turntonewdir
|
|
where
|
|
turntonewdir = magV (_prjAcc pj) *.* unitVectorAtAngle newdir
|
|
--i = _prjID pj
|
|
newdir
|
|
| SDL.ButtonRight `M.member` _mouseButtons w
|
|
&& w ^? cWorld . creatures . ix cid . crInvSel . iselPos
|
|
== w ^? cWorld . itemLocations . ix itid . ipInvID
|
|
= (w ^. cWorld . cwCam . cwcRot) + argV (_mousePos w)
|
|
| otherwise = _prjDir pj
|
|
|
|
doThrust :: Proj -> World -> World
|
|
doThrust pj w =
|
|
w
|
|
& randGen .~ g
|
|
& cWorld . projectiles . ix i . prjVel %~ (\v -> accel +.+ frict *.* v)
|
|
& soundContinue (ShellSound i) newPos missileLaunchS (Just 1)
|
|
& makeFlamelet (oldPos -.- vel) 0 (vel +.+ rotateV (pi + sparkD) accel) 3 10
|
|
& shellTrailCloud (addZ 20 (oldPos +.+ r1 +.+ 30 *.* normalizeV (oldPos -.- newPos)))
|
|
where
|
|
accel = _prjAcc pj
|
|
i = _prjID pj
|
|
oldPos = _prjPos pj
|
|
vel = _prjVel pj
|
|
newPos = oldPos +.+ vel
|
|
(frict, g) = randomR (0.6, 0.9) $ _randGen w
|
|
(sparkD, _) = randomR (-0.2, 0.2) $ _randGen w
|
|
r1 = randInCirc 10 & evalState $ _randGen w
|
|
|
|
trySpinByCID ::
|
|
-- | creature id
|
|
Int ->
|
|
-- | Spin amount
|
|
Int ->
|
|
Proj ->
|
|
World ->
|
|
World
|
|
trySpinByCID cid i pj w = w & cWorld . projectiles . ix pjid . prjSpin .~ newSpin
|
|
where
|
|
pjid = _prjID pj
|
|
dir = argV $ _prjVel pj
|
|
newSpin = case w ^? cWorld . creatures . ix cid of
|
|
Just cr -> negate $ min 0.2 $ max (-0.2) $ normalizeAnglePi (dir - _crDir cr) / spinFactor
|
|
_ -> 0
|
|
spinFactor = 5 * (6 - fromIntegral i)
|
|
|
|
pjTrack :: Int -> Proj -> World -> World
|
|
pjTrack itid pj w = rotateToTarget pj w
|
|
where
|
|
rotateToTarget _ = fromMaybe id $ do
|
|
tpos <- w ^? itPoint . itTargeting . tgPos . _Just
|
|
return $
|
|
cWorld . projectiles . ix (_prjID pj) . prjSpin
|
|
.~ turnToAmount
|
|
0.15
|
|
(_prjPos pj)
|
|
tpos
|
|
(argV $ _prjAcc pj)
|
|
itPoint = pointerToItemLocation $ _itemLocations (_cWorld w) IM.! itid
|
|
|
|
reduceSpinBy :: Float -> Proj -> World -> World
|
|
reduceSpinBy x pj = cWorld . projectiles . ix (_prjID pj) . prjSpin *~ x
|