Files
loop/src/Dodge/Creature/YourControl.hs
T
justin 81f88c32e9 Unify key press and mouse button press timings
Both now use Ints for presses.
Still no release timer for keyboard events.
2025-07-28 23:16:05 +01:00

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