81f88c32e9
Both now use Ints for presses. Still no release timer for keyboard events.
233 lines
7.0 KiB
Haskell
233 lines
7.0 KiB
Haskell
{-# LANGUAGE LambdaCase #-}
|
|
|
|
module Dodge.Creature.YourControl (
|
|
yourControl,
|
|
) where
|
|
|
|
import Dodge.Creature.MoveType
|
|
import Dodge.Data.Equipment.Misc
|
|
import Control.Monad
|
|
import qualified Data.Map.Strict as M
|
|
import Data.Maybe
|
|
import Dodge.Creature.Impulse.Movement
|
|
import Dodge.Creature.Impulse.UseItem
|
|
import Dodge.Data.AimStance
|
|
import Dodge.Data.World
|
|
import Dodge.AssignHotkey
|
|
import Dodge.InputFocus
|
|
import Dodge.Inventory
|
|
import Dodge.Item.AimStance
|
|
import Dodge.SelectedClose
|
|
import Dodge.WASD
|
|
import Geometry
|
|
import LensHelp
|
|
import NewInt
|
|
import qualified SDL
|
|
|
|
-- | The AI equivalent for your control.
|
|
yourControl :: Creature -> World -> World
|
|
yourControl _ w
|
|
| inTextInputFocus w = w
|
|
| Just x <- w ^? hud . hudElement . subInventory
|
|
, f x =
|
|
w
|
|
& cWorld . lWorld . creatures . ix 0 %~ wasdWithAiming w
|
|
& tryClickUse pkeys
|
|
& handleHotkeys
|
|
| otherwise =
|
|
w & cWorld . lWorld . creatures . ix 0 %~ wasdWithAiming w
|
|
where
|
|
f NoSubInventory = True
|
|
f ExamineInventory = True
|
|
f _ = False
|
|
pkeys = w ^. input . mouseButtons
|
|
|
|
handleHotkeys :: World -> World
|
|
handleHotkeys w
|
|
| ispressed SDL.ScancodeLShift || ispressed SDL.ScancodeRShift
|
|
, Just hk <-
|
|
listToMaybe . mapMaybe scancodeToHotkey . M.keys $ w ^. input . pressedKeys
|
|
, Just invid <- lw ^? creatures . ix 0 . crManipulation . manObject . imSelectedItem
|
|
, Just itid <- lw ^? creatures . ix 0 . crInv . ix invid . itID =
|
|
w & cWorld . lWorld %~ assignHotkey itid hk
|
|
| ispressed SDL.ScancodeLCtrl || ispressed SDL.ScancodeRCtrl
|
|
, Just hk <-
|
|
listToMaybe . mapMaybe scancodeToHotkey . M.keys $
|
|
w ^. input . pressedKeys
|
|
, Just itid <- lw ^? hotkeys . ix hk . unNInt
|
|
, Just invid <- lw ^? itemLocations . ix itid . ilInvID =
|
|
w & invSetSelectionPos 0 invid
|
|
| otherwise =
|
|
M.foldl'
|
|
useHotkey
|
|
w
|
|
(M.intersectionWith (,) thehotkeys (w ^. input . pressedKeys))
|
|
where
|
|
ispressed k = k `M.member` _pressedKeys (_input w)
|
|
thehotkeys = M.mapKeys hotkeyToScancode $ w ^. cWorld . lWorld . hotkeys
|
|
lw = w ^. cWorld . lWorld
|
|
|
|
useHotkey :: World -> (NewInt ItmInt, Int) -> World
|
|
useHotkey w (NInt itid, pt) = fromMaybe w $ do
|
|
invid <- w ^? cWorld . lWorld . itemLocations . ix itid . ilInvID
|
|
useItem invid pt w
|
|
|
|
hotkeyToScancode :: Hotkey -> SDL.Scancode
|
|
hotkeyToScancode x = case x of
|
|
HotkeyQ -> SDL.ScancodeQ
|
|
HotkeyE -> SDL.ScancodeE
|
|
HotkeyR -> SDL.ScancodeE
|
|
HotkeyZ -> SDL.ScancodeZ
|
|
HotkeyX -> SDL.ScancodeX
|
|
HotkeyC -> SDL.ScancodeC
|
|
HotkeyV -> SDL.ScancodeV
|
|
Hotkey1 -> SDL.Scancode1
|
|
Hotkey2 -> SDL.Scancode2
|
|
Hotkey3 -> SDL.Scancode3
|
|
Hotkey4 -> SDL.Scancode4
|
|
Hotkey5 -> SDL.Scancode5
|
|
Hotkey6 -> SDL.Scancode6
|
|
Hotkey7 -> SDL.Scancode7
|
|
Hotkey8 -> SDL.Scancode8
|
|
Hotkey9 -> SDL.Scancode9
|
|
Hotkey0 -> SDL.Scancode0
|
|
|
|
scancodeToHotkey :: SDL.Scancode -> Maybe Hotkey
|
|
scancodeToHotkey x = case x of
|
|
SDL.ScancodeQ -> Just HotkeyQ
|
|
SDL.ScancodeE -> Just HotkeyE
|
|
SDL.ScancodeR -> Just HotkeyR
|
|
SDL.ScancodeZ -> Just HotkeyZ
|
|
SDL.ScancodeX -> Just HotkeyX
|
|
SDL.ScancodeC -> Just HotkeyC
|
|
SDL.ScancodeV -> Just HotkeyV
|
|
SDL.Scancode1 -> Just Hotkey1
|
|
SDL.Scancode2 -> Just Hotkey2
|
|
SDL.Scancode3 -> Just Hotkey3
|
|
SDL.Scancode4 -> Just Hotkey4
|
|
SDL.Scancode5 -> Just Hotkey5
|
|
SDL.Scancode6 -> Just Hotkey6
|
|
SDL.Scancode7 -> Just Hotkey7
|
|
SDL.Scancode8 -> Just Hotkey8
|
|
SDL.Scancode9 -> Just Hotkey9
|
|
SDL.Scancode0 -> Just Hotkey0
|
|
_ -> Nothing
|
|
|
|
{- | The order of these MAY be important, in particular the setting of crMvAim
|
|
within wasdMovement should probably be done first
|
|
-}
|
|
wasdWithAiming :: World -> Creature -> Creature
|
|
wasdWithAiming w cr = wasdAim inp w $ wasdMovement inp cam speed cr
|
|
where
|
|
speed = _mvSpeed $ crMvType cr
|
|
inp = w ^. input
|
|
cam = w ^. wCam
|
|
|
|
wasdAim :: Input -> World -> Creature -> Creature
|
|
wasdAim inp w cr
|
|
| Just 0 <- inp ^? mouseButtons . ix SDL.ButtonRight
|
|
, Nothing <- inp ^? mouseButtons . ix SDL.ButtonLeft =
|
|
setAimPosture cr
|
|
| SDL.ButtonRight `M.member` _mouseButtons inp = aimTurn mousedir cr
|
|
| Aiming <- cr ^. crStance . posture = removeAimPosture cr
|
|
| otherwise = creatureTurnTowardDir (_crMvAim cr) 0.2 cr
|
|
where
|
|
mousedir = argV $ w ^. cWorld . lWorld . lAimPos - (cr ^. crPos)
|
|
|
|
setAimPosture :: Creature -> Creature
|
|
setAimPosture = (crStance . posture .~ Aiming) . doAimTwist (- twoHandTwistAmount)
|
|
|
|
doAimTwist :: Float -> Creature -> Creature
|
|
doAimTwist x cr = fromMaybe cr $ do
|
|
itRef <- cr ^? crManipulation . manObject . imRootSelectedItem
|
|
astance <- fmap itemBaseStance $ cr ^? crInv . ix itRef
|
|
guard $ astance == TwoHandOver || astance == TwoHandUnder
|
|
return $ cr & crDir +~ x
|
|
|
|
removeAimPosture :: Creature -> Creature
|
|
removeAimPosture = (crStance . posture .~ AtEase) . doAimTwist twoHandTwistAmount
|
|
|
|
twoHandTwistAmount :: Float
|
|
twoHandTwistAmount = 1.6 * pi
|
|
|
|
wasdMovement :: Input -> Camera -> Float -> Creature -> Creature
|
|
wasdMovement inp cam speed = theMovement . setMvAim
|
|
where
|
|
setMvAim = fromMaybe id $ do
|
|
dir <- safeArgV movDir
|
|
return $ crMvAim .~ (cam ^. camRot + dir)
|
|
movDir = wasdDir inp
|
|
movAbs = rotateV (cam ^. camRot) $ normalizeV movDir
|
|
theMovement
|
|
| movDir == V2 0 0 = id
|
|
| otherwise = crMvAbsolute (speed *.* movAbs)
|
|
|
|
aimTurn :: Float -> Creature -> Creature
|
|
aimTurn a cr = creatureTurnTowardDir a (x * 0.2) cr
|
|
where
|
|
x = fromMaybe 1 $ do
|
|
itRef <- cr ^? crManipulation . manObject . imRootSelectedItem
|
|
fmap itemBulkiness $ cr ^? crInv . ix itRef . itType
|
|
|
|
itemBulkiness :: ItemType -> Float
|
|
itemBulkiness = \case
|
|
HELD hit -> heldItemBulkiness hit
|
|
_ -> 1
|
|
|
|
heldItemBulkiness :: HeldItemType -> Float
|
|
heldItemBulkiness = \case
|
|
BANGSTICK{} -> 1
|
|
REWINDER -> 1
|
|
TIMESTOPPER -> 1
|
|
TIMESCROLLER -> 1
|
|
PISTOL -> 1
|
|
MACHINEPISTOL -> 1
|
|
AUTOPISTOL -> 1
|
|
SMG -> 1
|
|
BANGCONE -> 1
|
|
BLUNDERBUSS -> 1
|
|
GRAPECANNON{} -> 1
|
|
MINIGUNX{} -> 0.5
|
|
VOLLEYGUN{} -> 1
|
|
RIFLE -> 1
|
|
ALTERIFLE -> 1
|
|
AUTORIFLE -> 1
|
|
BURSTRIFLE -> 1
|
|
BANGROD -> 1
|
|
ELEPHANTGUN -> 1
|
|
AMR -> 1
|
|
AUTOAMR -> 1
|
|
SNIPERRIFLE -> 1
|
|
FLAMESPITTER -> 1
|
|
FLAMETHROWER -> 1
|
|
FLAMETORRENT -> 1
|
|
FLAMEWALL -> 1
|
|
BLOWTORCH -> 1
|
|
SPARKGUN -> 1
|
|
TESLAGUN -> 1
|
|
LASER -> 1
|
|
TRACTORGUN -> 1
|
|
RLAUNCHER -> 0.9
|
|
RLAUNCHERX{} -> 0.9
|
|
GLAUNCHER -> 1
|
|
POISONSPRAYER -> 1
|
|
SHATTERGUN -> 1
|
|
TORCH -> 1
|
|
FLATSHIELD -> 0.5
|
|
KEYCARD{} -> 1
|
|
BLINKER -> 1
|
|
BLINKERUNSAFE -> 1
|
|
|
|
tryClickUse :: M.Map SDL.MouseButton Int -> World -> World
|
|
tryClickUse pkeys w = fromMaybe w $ do
|
|
ltime <- pkeys ^? ix SDL.ButtonLeft
|
|
rtime <- pkeys ^? ix SDL.ButtonRight
|
|
guard $ ltime <= rtime
|
|
case w
|
|
^? cWorld . lWorld . creatures . ix 0
|
|
. crManipulation
|
|
. manObject
|
|
. imSelectedItem of
|
|
Just invid -> useItem invid ltime w
|
|
Nothing -> interactWithCloseObj <$> getSelectedCloseObj w ?? w
|