426 lines
13 KiB
Haskell
426 lines
13 KiB
Haskell
module Dodge.HeldUse where
|
|
import Dodge.Data
|
|
import Dodge.Base.Coordinate
|
|
import Sound.Data
|
|
import Dodge.Bullet
|
|
import Dodge.Item.Weapon.TriggerType
|
|
import Dodge.SoundLogic
|
|
import Dodge.WorldEvent.Flash
|
|
import Dodge.Item.Location
|
|
import Dodge.Item.Weapon.Radar
|
|
import Dodge.Item.Weapon.BatteryGuns
|
|
import Dodge.Item.Weapon.SonicGuns
|
|
import Dodge.Item.Weapon.Utility
|
|
import Dodge.Item.Weapon.Shatter
|
|
import Dodge.Item.Weapon.Launcher
|
|
import Dodge.Projectile.Create
|
|
import Dodge.Gas
|
|
import Geometry
|
|
import qualified IntMapHelp as IM
|
|
import LensHelp
|
|
import RandomHelp
|
|
import Color
|
|
|
|
import Data.Maybe
|
|
import Data.Traversable
|
|
|
|
useMod :: HeldMod -> [(Item -> Creature -> World -> World) -> Item -> Creature -> World -> World]
|
|
useMod hm = case hm of
|
|
HeldModNothing -> []
|
|
PoisonSprayerMod ->
|
|
[ ammoCheckI
|
|
, withSoundForI foamSprayLoopS 5
|
|
, useAmmoAmount 1
|
|
]
|
|
FlameSpitterMod ->
|
|
[ ammoCheckI
|
|
, useTimeCheck
|
|
, lockInvFor 10
|
|
, repeatOnFrames [1..9]
|
|
, withRandomItemParams f
|
|
, useAmmoAmount 1
|
|
, withSidePushI 5
|
|
, withSidePushAfterI 20
|
|
]
|
|
FlameThrowerMod ->
|
|
[ ammoCheckI
|
|
, useAmmoAmount 1
|
|
, withSidePushI 5
|
|
--, withTempLight 1 100 (V3 1 0 0)
|
|
, withSidePushAfterI 20
|
|
]
|
|
LauncherMod ->
|
|
[ hammerCheckI
|
|
, ammoCheckI
|
|
, useTimeCheck
|
|
, withSoundStart tap4S
|
|
, useAmmoAmount 1
|
|
]
|
|
TeslaMod ->
|
|
[ ammoCheckI
|
|
, withTempLight 1 100 (V3 0 0 1)
|
|
, withSoundForI elecCrackleS 1
|
|
, useAmmoAmount 1
|
|
]
|
|
CircleLaserMod ->
|
|
[ ammoCheckI
|
|
, withItem $ \it -> withTempLight 1 100 (xyzV4 (_lasColor $ _itParams it))
|
|
, withItem $ \it -> withMuzPos $ flareCircleAt (_lasColor $ _itParams it) 0.8
|
|
, withSoundForI tone440sawtoothquietS 2
|
|
, useAmmoAmount 1
|
|
, withItemUpdate' increasecycleLasCircle
|
|
, duplicateItem fLasCircle
|
|
]
|
|
LasWideMod n ->
|
|
[ ammoCheckI
|
|
, withItem $ \it -> withTempLight 1 100 (xyzV4 (_lasColor $ _itParams it))
|
|
, withItem $ \it -> withMuzPos $ flareCircleAt (_lasColor $ _itParams it) 0.8
|
|
, withSoundForI tone440sawtoothquietS 2
|
|
, useAmmoAmount 1
|
|
, crAtMuzPos
|
|
, withItemUpdate' (increasecycleLasWide n)
|
|
, withItem $ \it -> duplicateOffsetsV2 (xsLasWide it)
|
|
]
|
|
DualBeamMod ->
|
|
[ ammoCheckI
|
|
, withItem $ \it -> withMuzPosShift (V2 0 (thegapDualBeam it)) $ flareCircleAt (_lasColor $ _itParams it) 0.8
|
|
, withItem $ \it -> withMuzPosShift (V2 0 (-thegapDualBeam it)) $ flareCircleAt (_lasColor2 $ _itParams it) 0.8
|
|
, withSoundForI tone440sawtoothquietS 2
|
|
, useAmmoAmount 1
|
|
]
|
|
LasMod ->
|
|
[ ammoCheckI
|
|
, withItem $ \it -> withTempLight 1 100 (xyzV4 (_lasColor $ _itParams it))
|
|
, withSoundForI tone440sawtoothquietS 2
|
|
, withItem $ \it -> withMuzPos $ flareCircleAt (_lasColor $ _itParams it) 0.8
|
|
, useAmmoAmount 1
|
|
, crAtMuzPos
|
|
]
|
|
LauncherXMod i ->
|
|
[ hammerCheckI
|
|
, ammoCheckI
|
|
, useTimeCheck
|
|
, withSoundStart tap4S
|
|
, useAmmoAmount i
|
|
]
|
|
ShatterMod ->
|
|
[ ammoHammerCheck
|
|
, useTimeCheck
|
|
-- , withSoundStart tap3S
|
|
, useAmmoAmount 1
|
|
]
|
|
AmmoCheckMod -> [ ammoCheckI ]
|
|
AmmoUseCheckMod -> [ ammoUseCheck ]
|
|
AmmoHammerTimeUseOneMod ->
|
|
[ ammoHammerCheck
|
|
, useTimeCheck
|
|
, useAmmoAmount 1
|
|
]
|
|
BangCaneMod ->
|
|
[ ammoHammerCheck
|
|
, useTimeCheck
|
|
, withSoundStart tap3S
|
|
, useAmmoAmount 1
|
|
, withTorqueAfter
|
|
, applyInaccuracy
|
|
, withRecoil
|
|
, withSmoke 1 black 20 200 5
|
|
, withMuzFlareI
|
|
]
|
|
VolleyGunMod ->
|
|
[ ammoHammerCheck
|
|
, useTimeCheck
|
|
, withSoundItemChoiceStart caneStickSoundChoice
|
|
, useAllAmmo
|
|
, withTorqueAfter
|
|
, duplicateLoadedBarrels
|
|
, applyInaccuracy
|
|
, withMuzFlareI
|
|
, withRecoil
|
|
]
|
|
AutoRifleMod -> -- note this is the same as BangCanemMod with the first changed
|
|
[ ammoCheckI
|
|
, useTimeCheck
|
|
, withSoundStart tap3S
|
|
, useAmmoAmount 1
|
|
, withTorqueAfter
|
|
, applyInaccuracy
|
|
, withRecoil
|
|
, withSmoke 1 black 20 200 5
|
|
, withMuzFlareI
|
|
]
|
|
BangRodMod ->
|
|
[ ammoHammerCheck
|
|
, useTimeCheck
|
|
, withSoundStart bangEchoS
|
|
, useAmmoAmount 1
|
|
, withTorqueAfter
|
|
, applyInaccuracy
|
|
, withThickSmokeI
|
|
, withMuzFlareI
|
|
, withRecoil
|
|
]
|
|
ElephantGunMod ->
|
|
[ ammoHammerCheck
|
|
, useTimeCheck
|
|
, withSoundStart bangEchoS
|
|
, useAmmoAmount 1
|
|
, withTorqueAfter
|
|
, applyInaccuracy
|
|
, withThickSmokeI
|
|
, withMuzFlareI
|
|
, withRecoil
|
|
]
|
|
AutoAmrMod ->
|
|
[ ammoCheckI -- cf ElephantGun
|
|
, useTimeCheck
|
|
, withSoundStart bangEchoS
|
|
, useAmmoAmount 1
|
|
, withTorqueAfter
|
|
, applyInaccuracy
|
|
, withThickSmokeI
|
|
, withMuzFlareI
|
|
, withRecoil
|
|
]
|
|
MachineGunMod ->
|
|
[ ammoCheckI
|
|
, rateIncAB (torqueBeforeAtLeast 0.1 0.1) withTorqueAfter
|
|
, withSoundStart bangEchoS
|
|
, withThinSmokeI
|
|
, withMuzFlareI
|
|
]
|
|
ModWithDirectedTeleport hm' ->
|
|
withPosDirWallCheck directedTelPos : useMod hm'
|
|
BangStickMod ->
|
|
[ ammoHammerCheck
|
|
, useTimeCheck
|
|
, withSoundItemChoiceStart bangStickSoundChoice
|
|
, useAllAmmo
|
|
, withMuzFlareI
|
|
, withTorqueAfter
|
|
, spreadLoaded
|
|
-- , applyInaccuracy
|
|
, withRecoil
|
|
]
|
|
PistolMod ->
|
|
[ ammoHammerCheck
|
|
, useTimeCheck
|
|
, useAmmoAmount 1
|
|
, withSoundStart tap3S
|
|
, applyInaccuracy
|
|
, withTorqueAfter
|
|
, withRecoil
|
|
, withSidePushI 50
|
|
, withMuzFlareI
|
|
]
|
|
AutoPistolMod ->
|
|
[ ammoCheckI
|
|
, useTimeCheck
|
|
, useAmmoAmount 1
|
|
, withSoundStart tap3S
|
|
, applyInaccuracy
|
|
, withTorqueAfter
|
|
, withRecoil
|
|
, withSidePushI 50
|
|
, withMuzFlareI
|
|
]
|
|
MachinePistolMod ->
|
|
[ ammoCheckI
|
|
, useTimeCheck
|
|
, useAmmoAmount 1
|
|
, withSoundStart tap1S
|
|
, applyInaccuracy
|
|
, withTorqueAfter
|
|
, withSidePushI 50
|
|
, withRecoil
|
|
, withMuzFlareI
|
|
]
|
|
BurstRifleMod ->
|
|
[ ammoHammerCheck
|
|
, useTimeCheck
|
|
, sideEffectOnFrame 7 (\_ cr -> TorqueCr 0.2 (_crID cr)) --(torqueSideEffect 0.2)
|
|
, lockInvFor 7
|
|
, \f' it -> repeatOnFrames (take (_laLoaded (_itConsumption it) - 1) [3,6]) f' it
|
|
, withSoundStart tap3S
|
|
, useAmmoAmount 1
|
|
, applyInaccuracy
|
|
, withMuzFlareI
|
|
, withRecoil
|
|
]
|
|
MiniGunMod i ->
|
|
[ ammoCheckI
|
|
, withWarmUp crankSlowS
|
|
, withSoundForI mini1S 2
|
|
--, withThinSmokeI
|
|
, withSmoke 1 black 20 200 5
|
|
, withMuzFlareI
|
|
, useAmmoAmount i
|
|
, withSidePushI (fromIntegral i * 50)
|
|
, torqueBefore (fromIntegral i * 0.05)
|
|
, afterRecoil (fromIntegral i * 5)
|
|
] <>
|
|
[ trigDoAlso' (moddelay x) (modcrpos x) useAmmoParams
|
|
| x <- map ((/fromIntegral i) . fromIntegral) [1..i-1]
|
|
]
|
|
SmgMod ->
|
|
[ ammoCheckI
|
|
, useTimeCheck
|
|
, useAmmoAmount 1
|
|
, withSoundStart tap3S
|
|
, applyInaccuracy
|
|
, withTorqueAfter
|
|
, withRecoil
|
|
, withSidePushI 30
|
|
, withMuzFlareI
|
|
]
|
|
RevolverXMod ->
|
|
[ ammoHammerCheck
|
|
, useTimeCheck
|
|
-- rather than locking the inventory, a better solution may be to check
|
|
-- that the weapon is still in your hands in the repeated frames
|
|
, lockInvFor 10
|
|
, \f' it -> repeatOnFrames (take (_laLoaded (_itConsumption it) - 1) [2,4,6,8,10]) f' it
|
|
, withSoundStart tap3S
|
|
, useAmmoUpTo 1
|
|
, applyInaccuracy
|
|
, withMuzFlareI
|
|
-- , spreadLoaded
|
|
, withTorqueAfter
|
|
, withRecoil
|
|
]
|
|
BangConeMod ->
|
|
[ ammoCheckI
|
|
, hammerCheckI
|
|
, useTimeCheck
|
|
, withSoundStart bangEchoS
|
|
, useAllAmmo
|
|
, withTorqueAfter
|
|
, withRecoil
|
|
, duplicateLoaded
|
|
, withMuzFlareI
|
|
, applyInaccuracy
|
|
, withRandomOffset
|
|
, withRandomItemUpdate coneRandItemUpdate
|
|
, withRandomItemParams coneRandItemParams
|
|
]
|
|
where
|
|
f = do
|
|
nzpres <- state $ randomR (3,4)
|
|
return $ sprayNozzles . ix 0 . nzPressure .~ nzpres
|
|
increasecycleLasCircle it = it & itParams . lasCycle %~ (flip mod 2000 . (+ 1))
|
|
--f it = [it & itParams . lasCycle +~ x | x <- [0,100 .. 1900] ]
|
|
fLasCircle it = [it & itParams . lasCycle +~ x | x <- [0,50 .. 1999] ]
|
|
increasecycleLasWide n it = case _useHammer (_itUse it) of
|
|
HammerUp -> it & itParams . lasCycle .~ 1
|
|
_ -> it & itParams . lasCycle %~ (min (n * 5) . (+ 1))
|
|
xsLasWide it = [ V2 ((0.2*yoff x) ^ (2::Int)) (yoff x) | x <- [(0::Int)..n'-1] ]
|
|
where
|
|
yoff x = fromIntegral x - fromIntegral (n'-1) / 2
|
|
n' = _lasCycle (_itParams it)
|
|
thegapDualBeam = _dbGap . _itParams
|
|
directedTelPos it cr w = (p,a)
|
|
where
|
|
p = fromMaybe (_crPos cr) $ it ^? itTargeting . tgPos . _Just
|
|
a = argV (mouseWorldPos w -.- p)
|
|
moddelay x = itConsumption . laAmmoType . amBullet . buState .~ DelayedBullet x
|
|
modcrpos x cr = cr & crDir %~ tweenAngles x (_crOldDir cr)
|
|
& crPos %~ tweenPoints x (_crOldPos cr)
|
|
|
|
useHeld :: HeldUse -> Item -> Creature -> World -> World
|
|
useHeld hu = case hu of
|
|
HeldDoNothing -> const $ const id
|
|
HeldUseAmmoParams -> useAmmoParams
|
|
HeldOverNozzlesUseGasParams -> overNozzles useGasParams
|
|
HeldPJCreation -> usePjCreation
|
|
HeldPJCreationX i -> usePjCreationX i
|
|
HeldFireRemoteShell -> fireRemoteShell
|
|
HeldDetectorEffect dt -> detectorEffect dt
|
|
HeldTeslaArc -> shootTeslaArc
|
|
HeldLaser -> shootLaser
|
|
HeldCircleLaser -> circleLaser
|
|
HeldDualLaser -> shootDualLaser
|
|
HeldTractor -> aTractorBeam
|
|
HeldSonicWave -> aSonicWave
|
|
HeldForceField -> useForceFieldGun
|
|
HeldShatter -> shootShatter
|
|
HeldExplodeRemoteShell itid pjid -> const $ const $ explodeRemoteRocket itid pjid
|
|
|
|
usePjCreation :: Item -> Creature -> World -> World
|
|
usePjCreation it = createProjectile (_amPjCreation (_laAmmoType (_itConsumption it))) it
|
|
|
|
usePjCreationX :: Int -> Item -> Creature -> World -> World
|
|
usePjCreationX i it cr = foldr f
|
|
(createProjectile (_amPjCreation (_laAmmoType (_itConsumption it))) it cr)
|
|
[1..i-1]
|
|
where
|
|
f n = (. createProjectile (_amPjCreation (_laAmmoType (_itConsumption it))) it (cr & crDir +~ (2*pi*fromIntegral n / fromIntegral i)))
|
|
|
|
overNozzles :: (Nozzle -> Item -> Creature -> World -> World)
|
|
-> Item -> Creature -> World -> World
|
|
overNozzles = overNozzles' . overNozzle
|
|
|
|
overNozzles' :: (Item -> Creature -> World -> Nozzle -> (World,Nozzle))
|
|
-> Item -> Creature -> World -> World
|
|
overNozzles' eff it cr w = neww & creatures . ix cid . crInv . ix i . itParams . sprayNozzles .~ newNozzles
|
|
where
|
|
cid = _crID cr
|
|
i = crSel $ _creatures w IM.! cid
|
|
(neww,newNozzles) = mapAccumR (eff it cr) w $ _sprayNozzles (_itParams it)
|
|
|
|
overNozzle :: (Nozzle -> Item -> Creature -> World -> World)
|
|
-> Item -> Creature -> World -> Nozzle -> (World, Nozzle)
|
|
overNozzle eff it cr w nz =
|
|
( eff nz it (cr & crDir +~ wa + na) w & randGen .~ g
|
|
, nz & nzCurrentWalkAngle .~ wa)
|
|
where
|
|
na = _nzDir nz
|
|
(walkamount, g) = randomR (-aspeed,aspeed) (_randGen w)
|
|
aspeed = _nzWalkSpeed nz
|
|
maxa = _nzMaxWalkAngle nz
|
|
wa = min maxa $ max (negate maxa) (_nzCurrentWalkAngle nz + walkamount)
|
|
|
|
useGasParams :: Nozzle -> Item -> Creature -> World -> World
|
|
useGasParams nz it cr = createGas (_amCreateGas (_laAmmoType (_itConsumption it)))
|
|
(_nzPressure nz) pos dir cr
|
|
where
|
|
dir = _crDir cr
|
|
pos = _crPos cr +.+ (_nzLength nz *.* unitVectorAtAngle (_crDir cr))
|
|
|
|
fireRemoteShell :: Item -> Creature -> World -> World
|
|
fireRemoteShell it cr w = set (creatures . ix cid . crInv . ix j . itUse . rUse)
|
|
(HeldExplodeRemoteShell itid i)
|
|
$ addRemRocket w'
|
|
where
|
|
(w',itid) = getHeldItemLoc cr w
|
|
i = IM.newKey $ _props w
|
|
cid = _crID cr
|
|
addRemRocket = makeShell it cr
|
|
[ PJSetScope itid
|
|
, PJThrust 330 0
|
|
, PJRemoteDirection 340 0 cid itid
|
|
]
|
|
j = crSel cr
|
|
|
|
caneStickSoundChoice :: Item -> SoundID
|
|
caneStickSoundChoice it
|
|
| _laLoaded (_itConsumption it) < 2 = tap3S
|
|
| otherwise = shotgunS
|
|
|
|
bangStickSoundChoice :: Item -> SoundID
|
|
bangStickSoundChoice it
|
|
| _laLoaded (_itConsumption it) < 2 = tap3S
|
|
| otherwise = shotgunS
|
|
|
|
coneRandItemUpdate :: State StdGen (Item -> Item)
|
|
coneRandItemUpdate = do
|
|
wth <- state $ randomR (1,5)
|
|
return (itConsumption . laAmmoType . amBullet . buWidth .~ wth)
|
|
coneRandItemParams :: State StdGen (ItemParams -> ItemParams)
|
|
coneRandItemParams = do
|
|
muzv <- state $ randomR (0.5,1)
|
|
rifl <- state $ randomR (0.3,0.9)
|
|
return $ \itparams -> itparams
|
|
{ _muzVel = muzv
|
|
, _rifling = rifl
|
|
}
|