Reorganise weapons, start work on drones
This commit is contained in:
+23
-355
@@ -1,361 +1,29 @@
|
||||
{- | Definitions of weapons.
|
||||
In progress: move out effects into other modules. -}
|
||||
module Dodge.Item.Weapon where
|
||||
import Dodge.Data
|
||||
import Dodge.Base
|
||||
import Dodge.Zone
|
||||
import Dodge.Picture.Layer
|
||||
import Dodge.SoundLogic
|
||||
import Dodge.WorldEvent
|
||||
import Dodge.Default
|
||||
import Dodge.Item.Draw
|
||||
{- | Rexport all weapons -}
|
||||
module Dodge.Item.Weapon
|
||||
( module Dodge.Item.Weapon.BulletGuns
|
||||
, module Dodge.Item.Weapon.TriggerType
|
||||
, module Dodge.Item.Weapon.ExtraEffect
|
||||
, module Dodge.Item.Weapon.UseEffect
|
||||
, module Dodge.Item.Weapon.Remote
|
||||
, module Dodge.Item.Weapon.Grenade
|
||||
, module Dodge.Item.Weapon.Spawn
|
||||
, module Dodge.Item.Weapon.Radar
|
||||
, module Dodge.Item.Weapon.Utility
|
||||
, module Dodge.Item.Weapon.SprayGuns
|
||||
, module Dodge.Item.Weapon.BatteryGuns
|
||||
, module Dodge.Item.Weapon.Launcher
|
||||
, module Dodge.Item.Weapon.Bezier
|
||||
) where
|
||||
import Dodge.Item.Weapon.BulletGuns
|
||||
import Dodge.Item.Weapon.TriggerType
|
||||
import Dodge.Item.Weapon.ExtraEffect
|
||||
import Dodge.Item.Weapon.UseEffect
|
||||
import Dodge.Item.Weapon.Remote
|
||||
import Dodge.Default.Weapon
|
||||
import Dodge.Item.Weapon.Grenade
|
||||
import Geometry
|
||||
import Picture
|
||||
import qualified IntMapHelp as IM
|
||||
import Shape
|
||||
import ShapePicture
|
||||
|
||||
import Data.Maybe
|
||||
import Data.Function
|
||||
import Control.Lens
|
||||
|
||||
effectGun :: String -> (Creature -> World -> World) -> Item
|
||||
effectGun name eff = defaultGun
|
||||
{ _itName = name ++ "Gun"
|
||||
, _itUse = const eff
|
||||
}
|
||||
autoEffectGun :: String -> (Creature -> World -> World) -> Item
|
||||
autoEffectGun name eff = defaultAutoGun
|
||||
{ _itName = name ++ "Gun"
|
||||
, _itUse = const eff
|
||||
}
|
||||
forceFieldGun :: Item
|
||||
forceFieldGun = defaultGun
|
||||
{ _itName = "FORCEFIELD"
|
||||
, _itIdentity = ForceFieldGun
|
||||
, _wpMaxAmmo = 100
|
||||
, _wpLoadedAmmo = 100
|
||||
, _wpReloadTime = 40
|
||||
, _wpReloadState = 0
|
||||
, _itUseRate = 10
|
||||
, _itUseTime = 0
|
||||
, _itUse = undefined
|
||||
, _wpSpread = 0.02
|
||||
, _wpRange = 20
|
||||
, _itFloorPict = \_ -> (,) emptySH $ onLayer FlItLayer $ polygon $ map toV2 [(-4,-4),(-4,4),(4,4),(4,0),(0,0),(0,-4)]
|
||||
, _itAimingSpeed = 0.4
|
||||
, _itAimingRange = 0.5
|
||||
}
|
||||
-- grapGun = defaultGun
|
||||
-- { _itName = "grapGun"
|
||||
-- , _itIdentity = GrapGun
|
||||
-- , _wpMaxAmmo = 1
|
||||
-- , _wpLoadedAmmo = 1
|
||||
-- , _wpReloadTime = 40
|
||||
-- , _wpReloadState = 0
|
||||
-- , _itUseRate = 10
|
||||
-- , _itUseTime = 0
|
||||
-- , _itUse = grapFire
|
||||
-- , _wpSpread = 0.002
|
||||
-- , _wpRange = 20
|
||||
-- , _wpIsAuto = False
|
||||
-- , _itFloorPict = onLayer FlItLayer $ polygon [(-4,-4),(-4,4),(4,4),(4,0),(0,0),(0,-4)]
|
||||
-- , _itAmount = 1
|
||||
-- , _itMaxStack = 1
|
||||
-- , _itAimingSpeed = 1
|
||||
-- , _itAimingRange = 0.5
|
||||
-- }
|
||||
|
||||
removeItAttachment :: Int -> Int -> World -> World
|
||||
removeItAttachment i _ w = w & creatures . ix i . crInv . ix itRef . itAttachment .~ NoItAttachment
|
||||
where
|
||||
cr = _creatures w IM.! i
|
||||
itRef = _crInvSel cr
|
||||
|
||||
shellExplosionAt :: Point2 -> World -> World
|
||||
shellExplosionAt = makeExplosionAt
|
||||
|
||||
reflect :: Float -> Float -> Float
|
||||
reflect a b = a + 2*(a-b)
|
||||
|
||||
retireRemoteBomb :: Int -> Int -> Int -> World -> World
|
||||
retireRemoteBomb itid 0 pjid w = w
|
||||
& pointToItem (_itemPositions w IM.! itid) %~
|
||||
( (itAttachment . scopePos .~ V2 0 0)
|
||||
. (itZoom .~ defaultItZoom)
|
||||
. (itUse .~ const throwRemoteBomb)
|
||||
)
|
||||
& props %~ IM.delete pjid
|
||||
retireRemoteBomb itid t pjid w = setScope w
|
||||
& props . ix pjid . pjUpdate .~ (\_ -> retireRemoteBomb itid (t-1) pjid)
|
||||
where
|
||||
setScope w' = case _itemPositions w' IM.! itid of
|
||||
InInv cid invid -> w'
|
||||
& creatures . ix cid . crInv . ix invid . itAttachment
|
||||
. scopePos .~ (pos -.- _crPos (_creatures w' IM.! cid))
|
||||
_ -> w'
|
||||
pos = fromMaybe (V2 0 0) $ w ^? props . ix pjid . pjPos
|
||||
|
||||
moveRemoteBomb :: Int -> Int -> Int -> World -> World
|
||||
moveRemoteBomb itid time pID w
|
||||
| time < -4 = updatePicture
|
||||
$ set (props .ix pID.pjUpdate) (\_ -> moveRemoteBomb itid (f time) pID)
|
||||
w
|
||||
| time < 2 = case hitWl of
|
||||
Just (p,_) -> soundStart (Tap 0) p tapQuietS Nothing $ halfV updatedWorld
|
||||
_ -> halfV updatedWorld
|
||||
| otherwise = case hitWl of
|
||||
Just (p,_) -> soundStart (Tap 0) p tapQuietS Nothing updatedWorld
|
||||
_ -> updatedWorld
|
||||
where
|
||||
updatedWorld
|
||||
= updateV $ set (props . ix pID . pjPos) finalPos
|
||||
$ updatePicture
|
||||
$ set (props .ix pID.pjUpdate) (\_ -> moveRemoteBomb itid (time-1) pID)
|
||||
w
|
||||
pj = _props w IM.! pID
|
||||
oldPos = _pjPos pj
|
||||
newPos = _pjVel pj +.+ oldPos
|
||||
-- this is hacky, should use a version of collidePointWalls' that collides
|
||||
-- circles and walls
|
||||
invShift x = x -.- 5 *.* normalizeV (_pjVel pj)
|
||||
hitWl = collideCircWalls oldPos newPos 4 $ wallsNearPoint newPos w
|
||||
finalPos = maybe newPos (invShift . fst) hitWl
|
||||
setV v = set (props . ix pID . pjVel) v
|
||||
updateV = maybe id (setV . snd) hitWl
|
||||
halfV = props . ix pID . pjVel %~ (0.5 *.*)
|
||||
f x | x < -369 = -10
|
||||
| otherwise = x - 1
|
||||
updatePicture =
|
||||
set (props . ix pID . prDraw)
|
||||
(\_ -> (,) mempty $ onLayer PtLayer $ uncurryV translate newPos $ remoteBombPic time)
|
||||
|
||||
|
||||
setRemoteBombScope :: Int -> Prop -> World -> World
|
||||
setRemoteBombScope itid pj w' = case _itemPositions w' IM.! itid of
|
||||
InInv cid invid
|
||||
-> w' & creatures . ix cid . crInv . ix invid . itAttachment
|
||||
. scopePos .~ (_pjPos pj -.- _crPos (_creatures w' IM.! cid))
|
||||
& creatures . ix cid . crInv . ix invid . itAimZoom
|
||||
.~ (defaultItZoom {_itZoomMax = 0.5, _itZoomMin = 0.5})
|
||||
_ -> w'
|
||||
|
||||
defaultThrowable :: Item
|
||||
defaultThrowable = grenade
|
||||
remoteBomb :: Item
|
||||
remoteBomb = defaultThrowable
|
||||
{ _itName = "REMOTEBOMB"
|
||||
, _itIdentity = RemoteBomb
|
||||
, _itMaxStack = 1
|
||||
, _itAmount = 1
|
||||
, _itFloorPict = \_ -> (,) emptySH $ onLayer FlItLayer $ polygon $ map toV2
|
||||
[(-3,-3),(-3,3),(3,3),(3,-3)]
|
||||
, _twMaxRange = 150
|
||||
, _twAccuracy = 30
|
||||
, _itUse = const throwRemoteBomb
|
||||
, _itUseModifiers =
|
||||
[ hammerCheckI
|
||||
]
|
||||
, _itAttachment = ItScope (V2 0 0) 0 1 True
|
||||
, _itEquipPict = pictureWeaponOnAim' $ \_ -> (,) emptySH remoteBombUnarmedPic
|
||||
}
|
||||
|
||||
|
||||
throwRemoteBomb :: Creature -> World -> World
|
||||
throwRemoteBomb cr w = setLocation
|
||||
$ removePict
|
||||
$ resetFire
|
||||
$ resetName
|
||||
$ over props addG w
|
||||
where
|
||||
cid = _crID cr
|
||||
addG = IM.insert i $ Projectile
|
||||
{ _pjPos = p
|
||||
, _pjStartPos = p
|
||||
, _pjVel = v
|
||||
, _prDraw = const mempty
|
||||
, _pjID = i
|
||||
, _pjUpdate = \_ -> moveRemoteBomb itid 50 i
|
||||
}
|
||||
i = newProjectileKey w
|
||||
v' = 0.02 / _cameraZoom w *.* rotateV (_cameraRot w) ( _mousePos w)
|
||||
v | magV v' > 6 = 6 *.* normalizeV v'
|
||||
| otherwise = v'
|
||||
j = _crInvSel cr
|
||||
resetName = set (creatures . ix cid . crInv . ix j . itName) "REMOTE"
|
||||
removePict = set (creatures . ix cid . crInv . ix j . itEquipPict) $ \ _ _ -> emptyBlank
|
||||
resetFire = set (creatures . ix cid . crInv . ix j . itUse)
|
||||
$ \_ -> explodeRemoteBomb itid i
|
||||
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'
|
||||
maybeitid = w ^? creatures . ix cid . crInv . ix j . itID . _Just
|
||||
setLocation :: World -> World
|
||||
setLocation w' = case maybeitid of
|
||||
Nothing -> w' & creatures . ix cid . crInv . ix j . itID ?~ newitid
|
||||
& itemPositions %~ IM.insert newitid (InInv cid j)
|
||||
_ -> w'
|
||||
newitid = IM.newKey $ _itemPositions w
|
||||
itid = fromMaybe newitid maybeitid
|
||||
|
||||
explodeRemoteBomb :: Int -> Int -> Creature -> World -> World
|
||||
explodeRemoteBomb itid pjid cr w
|
||||
= set (props . ix pjid . pjUpdate) (\_ -> retireRemoteBomb itid 30 pjid)
|
||||
-- $ set (props . ix pjid . pjDraw) (\_ -> blank)
|
||||
$ set (creatures . ix cid . crInv . ix j . itUse) (\_ -> const id)
|
||||
$ resetName
|
||||
$ resetPict
|
||||
-- $ resetScope
|
||||
$ makeExplosionAt (_pjPos (_props w IM.! pjid)) w
|
||||
-- - $ makeShrapnelBombAt (_pjPos (_props w IM.! pjid)) w
|
||||
where
|
||||
cid = _crID cr
|
||||
resetName = set (creatures . ix cid . crInv . ix j . itName) "REMOTEBOMB"
|
||||
resetPict = set (creatures . ix cid . crInv . ix j . itEquipPict )
|
||||
(pictureWeaponOnAim' $ \_ -> (,) emptySH remoteBombUnarmedPic)
|
||||
-- resetScope = creatures . ix cid . crInv . ix j . itScope . _Just . scopePos .~ (0,0)
|
||||
j = _crInvSel $ _creatures w IM.! cid
|
||||
remoteBombPic
|
||||
:: Int -- ^ time
|
||||
-> Picture
|
||||
remoteBombPic _ = pictures
|
||||
[ color (dark $ dark orange) $ circleSolid 5
|
||||
]
|
||||
|
||||
remoteBombUnarmedPic :: Picture
|
||||
remoteBombUnarmedPic = color (dark $ dark orange) $ circleSolid 5
|
||||
|
||||
pipe :: Item
|
||||
pipe = Craftable
|
||||
{ _itIdentity = Generic
|
||||
, _itDimension = defaultItemDimension
|
||||
, _itCurseStatus = Uncursed
|
||||
, _itName = "PIPE"
|
||||
, _itMaxStack = 3
|
||||
, _itAmount = 3
|
||||
, _itFloorPict = \_ -> (,) emptySH $ onLayer FlItLayer $ polygon $ map toV2 [(-3,-3),(-3,3),(3,3),(3,-3)]
|
||||
, _itEquipPict = \_ _ -> emptyBlank
|
||||
, _itID = Nothing
|
||||
, _itInvDisplay = _itName
|
||||
, _itInvColor = green
|
||||
, _itAimStance = LeaveHolstered
|
||||
}
|
||||
{- |
|
||||
Sends out pulses that display walls. -}
|
||||
radar :: Item
|
||||
radar = defaultGun
|
||||
{ _itName = "RADAR"
|
||||
, _itIdentity = Generic
|
||||
, _wpMaxAmmo = 100
|
||||
, _wpLoadedAmmo = 100
|
||||
, _wpReloadTime = 200
|
||||
, _wpReloadState = 0
|
||||
, _itUseRate = 120
|
||||
, _itUseTime = 0
|
||||
, _itUse = const aRadarPulse
|
||||
, _itUseModifiers =
|
||||
[ ammoUseCheckI
|
||||
]
|
||||
, _wpSpread = autogunSpread
|
||||
, _wpRange = 20
|
||||
, _itHammer = HammerUp
|
||||
, _itFloorPict = \_ -> (,) emptySH $ onLayer FlItLayer $ color blue $ polygon $ rectNESW 5 5 (-5) (-5)
|
||||
, _itAimingRange = 1
|
||||
, _itZoom = defaultItZoom { _itZoomMax = 1}
|
||||
, _itAimZoom = defaultItZoom { _itZoomMax = 1}
|
||||
, _itEquipPict = pictureWeaponOnAim' $ \_ -> (,) emptySH $ color blue $ polygon $ rectNESW 5 5 (-5) (-5)
|
||||
}
|
||||
{- |
|
||||
Sends out pulses that display creatures. -}
|
||||
sonar :: Item
|
||||
sonar = defaultGun
|
||||
{ _itName = "SONAR"
|
||||
, _itIdentity = Generic
|
||||
, _wpMaxAmmo = 100
|
||||
, _wpLoadedAmmo = 100
|
||||
, _wpReloadTime = 200
|
||||
, _wpReloadState = 0
|
||||
, _itUseRate = 120
|
||||
, _itUseTime = 0
|
||||
, _itUse = const aSonarPulse
|
||||
, _itUseModifiers =
|
||||
[ ammoUseCheckI
|
||||
]
|
||||
, _wpRange = 20
|
||||
, _itHammer = HammerUp
|
||||
, _itFloorPict = \_ -> (,) emptySH $ onLayer FlItLayer $ color blue $ polygon $ rectNESW 5 5 (-5) (-5)
|
||||
, _itAimingRange = 1
|
||||
, _itZoom = defaultItZoom {_itZoomMax = 1}
|
||||
, _itAimZoom = defaultItZoom {_itZoomMax = 1}
|
||||
, _itEquipPict = pictureWeaponOnAim' $ \_ -> (,) emptySH $ color blue $ polygon $ rectNESW 5 5 (-5) (-5)
|
||||
}
|
||||
{- |
|
||||
Automatically sends out pulses that display creatures. -}
|
||||
autoSonar :: Item
|
||||
autoSonar = defaultEquipment
|
||||
{ _itIdentity = Generic
|
||||
, _itName = "AUTOSONAR"
|
||||
, _itMaxStack = 1
|
||||
, _itAmount = 1
|
||||
, _itFloorPict = \_ -> (,) emptySH $ onLayer FlItLayer $ color yellow $ polygon $ map toV2 [(-3,-3),(-3,3),(3,3),(3,-3)]
|
||||
, _itEquipPict = \_ _ -> (,) emptySH blank
|
||||
, _itEffect = autoSonarEffect
|
||||
, _itID = Nothing
|
||||
, _itAimingSpeed = 1
|
||||
, _itAimingRange = 0
|
||||
, _itZoom = defaultItZoom {_itZoomMax = 1}
|
||||
, _itAimZoom = defaultItZoom {_itZoomMax = 1}
|
||||
}
|
||||
{- |
|
||||
Automatically sends out pulses that display walls. -}
|
||||
autoRadar :: Item
|
||||
autoRadar = defaultEquipment
|
||||
{ _itIdentity = Generic
|
||||
, _itName = "AUTORADAR"
|
||||
, _itMaxStack = 1
|
||||
, _itAmount = 1
|
||||
, _itFloorPict = \_ -> (,) emptySH $ onLayer FlItLayer $ color yellow $ polygon $ map toV2 [(-3,-3),(-3,3),(3,3),(3,-3)]
|
||||
, _itEquipPict = \_ _ -> (,) emptySH blank
|
||||
, _itEffect = autoRadarEffect
|
||||
, _itID = Nothing
|
||||
, _itAimingSpeed = 1
|
||||
, _itAimingRange = 0
|
||||
, _itZoom = defaultItZoom {_itZoomMax = 1}
|
||||
, _itAimZoom = defaultItZoom {_itZoomMax = 1}
|
||||
}
|
||||
{- |
|
||||
Creates a creature next to the creature using the item. -}
|
||||
spawnGun :: Creature -> Item
|
||||
spawnGun cr = defaultGun
|
||||
{ _itName = "SPAWNER"
|
||||
, _wpMaxAmmo = 1
|
||||
, _wpLoadedAmmo = 1
|
||||
, _wpReloadTime = 80
|
||||
, _wpReloadState = 0
|
||||
, _itUseRate = 100
|
||||
, _itUse = \_ -> spawnCrNextTo cr
|
||||
, _itUseModifiers =
|
||||
[ ammoCheckI
|
||||
, hammerCheckI
|
||||
]
|
||||
}
|
||||
spawnCrNextTo
|
||||
:: Creature -- ^ Creature to spawn
|
||||
-> Creature -- ^ existing creature that will be spawned next to
|
||||
-> World
|
||||
-> World
|
||||
spawnCrNextTo cr sCr w = w & creatures %~ IM.insert k newCr
|
||||
where
|
||||
k = IM.newKey $ _creatures w
|
||||
newCr = cr
|
||||
& crID .~ k
|
||||
& crPos .~ _crPos sCr +.+ unitVectorAtAngle (_crDir sCr)
|
||||
& crOldPos .~ _crPos sCr +.+ unitVectorAtAngle (_crDir sCr)
|
||||
|
||||
import Dodge.Item.Weapon.Spawn
|
||||
import Dodge.Item.Weapon.Utility
|
||||
import Dodge.Item.Weapon.Radar
|
||||
import Dodge.Item.Weapon.SprayGuns
|
||||
import Dodge.Item.Weapon.BatteryGuns
|
||||
import Dodge.Item.Weapon.Launcher
|
||||
import Dodge.Item.Weapon.Bezier
|
||||
|
||||
Reference in New Issue
Block a user