129 lines
4.0 KiB
Haskell
129 lines
4.0 KiB
Haskell
{- | Actions performed by creatures within the world
|
|
-}
|
|
module Dodge.Creature.Action
|
|
( module Dodge.Creature.Action
|
|
, module Dodge.Creature.Action.UseItem
|
|
, module Dodge.Creature.Action.Movement
|
|
)
|
|
where
|
|
import Dodge.Creature.Action.UseItem
|
|
import Dodge.Creature.Action.Movement
|
|
import Dodge.Creature.Stance.Data
|
|
--import Dodge.Creature.State.Data
|
|
import Dodge.WorldEvent.Shockwave
|
|
import Dodge.Data
|
|
import Dodge.Base
|
|
import Dodge.SoundLogic
|
|
--import Dodge.WorldEvent
|
|
import Dodge.Inventory
|
|
--import Dodge.LightSources
|
|
import Geometry
|
|
import Picture
|
|
import qualified IntMapHelp as IM
|
|
|
|
import Control.Lens
|
|
--import Control.Monad
|
|
--import Control.Applicative
|
|
import Data.Maybe
|
|
--import Data.List
|
|
import System.Random
|
|
--import qualified Data.Map as M
|
|
|
|
startReloadingWeapon
|
|
:: Creature
|
|
-> World
|
|
-> Maybe World
|
|
startReloadingWeapon cr w =
|
|
let cid = _crID cr
|
|
it = _crInv cr IM.! _crInvSel cr
|
|
itRef = creatures . ix cid . crInv . ix (_crInvSel cr)
|
|
in case it of
|
|
Weapon {_wpMaxAmmo=maxA,_wpLoadedAmmo=lA,_wpReloadState=rS,_wpReloadTime=rT}
|
|
| lA < maxA && rS == 0 -> Just $ set ( itRef . wpLoadedAmmo) maxA
|
|
$ set ( itRef . wpReloadState) rT w
|
|
_ -> Nothing
|
|
{- | Start reloading if clip is empty. -}
|
|
crAutoReload :: Creature -> Creature
|
|
crAutoReload cr = case cr ^? crInv . ix (_crInvSel cr) . wpLoadedAmmo of
|
|
Just 0 | _posture (_crStance cr) /= Aiming
|
|
-> cr & crInv . ix (_crInvSel cr) . wpReloadState %~ (`fromMaybe` reloadT)
|
|
& crInv . ix (_crInvSel cr) . wpLoadedAmmo %~ (`fromMaybe` maxA)
|
|
_ -> cr
|
|
where
|
|
reloadT = cr ^? crInv . ix (_crInvSel cr) . wpReloadTime
|
|
maxA = cr ^? crInv . ix (_crInvSel cr) . wpMaxAmmo
|
|
{- | Teleport a creature to the mouse position -}
|
|
blinkAction
|
|
:: Creature
|
|
-> World
|
|
-> World
|
|
blinkAction cr w = soundOnce teleSound
|
|
. set (creatures . ix cid . crPos) p3
|
|
. blinkShockwave cid p3
|
|
$ inverseShockwaveAt cpos 40 2 2 2 w
|
|
where
|
|
cid = _crID cr
|
|
p1 = mouseWorldPos w
|
|
cpos = _crPos cr
|
|
p2 = reflectPointWalls cpos p1 $ wallsAlongLine cpos p1 w
|
|
r = 1.5 * _crRad cr
|
|
p3 = maybe p1 (mvPointTowardAtSpeed r cpos . fst) p2
|
|
|
|
blinkShockwave
|
|
:: Int -- ^ Blinking creature ID.
|
|
-> Point2
|
|
-> World
|
|
-> World
|
|
blinkShockwave i p = makeShockwaveAt [i] p 60 1 2 cyan
|
|
|
|
{- | Get your creature to drop the item under the cursor. -}
|
|
youDropItem :: World -> World
|
|
youDropItem w = case yourItem w of
|
|
NoItem -> w
|
|
_ -> rmSelectedInvItem (_yourID w)
|
|
. copyItemToFloor (you w) (_crInvSel $ you w)
|
|
$ soundOnce putDownSound
|
|
w
|
|
{- | Copy an inventory item to the floor. -}
|
|
copyItemToFloor
|
|
:: Creature
|
|
-> Int -- ^ Inventory position
|
|
-> World
|
|
-> World
|
|
copyItemToFloor cr i w = case _crInv cr IM.! i of
|
|
NoItem -> w
|
|
it -> over floorItems (IM.insert flid theflit) . updateLocation $ set randGen g w
|
|
where
|
|
(rot, g) = randomR (-pi,pi) $ _randGen w
|
|
offset = (_crRad cr + 2) *.* unitVectorAtAngle rot
|
|
updateLocation w' = case it ^? itID of
|
|
Just (Just i') -> w' & itemPositions . ix i' .~ OnFloor flid
|
|
_ -> w'
|
|
flid = IM.newKey $ _floorItems w
|
|
theflit = FlIt
|
|
{_flIt = it
|
|
,_flItPos = offset +.+ _crPos cr
|
|
,_flItRot = rot
|
|
,_flItID = flid
|
|
}
|
|
{- | Pick up a specific item. -}
|
|
pickUpItem
|
|
:: Int -- ^ Creature id
|
|
-> FloorItem
|
|
-> World
|
|
-> World
|
|
pickUpItem cid flit w = case maybeInvSlot of
|
|
Nothing -> w
|
|
Just i -> w
|
|
& soundOnce pickUpSound
|
|
& updateItLocation i
|
|
& floorItems %~ IM.delete (_flItID flit)
|
|
& creatures . ix cid . crInv . ix i %~ addItem it
|
|
where
|
|
it = _flIt flit
|
|
maybeInvSlot = checkInvSlotsYou it w
|
|
updateItLocation invid w' = case _itID it of
|
|
Nothing -> w'
|
|
Just j -> w' & itemPositions . ix j .~ InInv 0 invid
|
|
|