Files
loop/src/Dodge/Creature/YourControl.hs
T
2025-05-31 22:11:26 +01:00

183 lines
6.0 KiB
Haskell

module Dodge.Creature.YourControl (
yourControl,
) where
import Control.Monad
import qualified Data.Map.Strict as M
import Data.Maybe
import Dodge.Base.Coordinate
import Dodge.Creature.Impulse.Movement
import Dodge.Creature.Impulse.UseItem
import Dodge.Data.World
import Dodge.Hotkey
import Dodge.InputFocus
import Dodge.Inventory
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 & augInvDirectSelect (0, invid, mempty)
| 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, PressType) -> 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 cam $ wasdMovement inp cam speed cr
where
speed = _mvSpeed $ _crMvType cr
inp = w ^. input
cam = w ^. wCam
wasdAim :: Input -> Camera -> Creature -> Creature
wasdAim inp cam 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 $ mouseWorldPos inp cam - (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 <- cr ^? crInv . ix itRef . itUse . heldAim . aimStance
return $ case astance of
TwoHandUnder -> cr & crDir +~ x
TwoHandOver -> cr & crDir +~ x
_ -> cr
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
cr ^? crInv . ix itRef . itUse . heldAim . aimTurnSpeed
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 (f ltime) w
Nothing -> interactWithCloseObj <$> getSelectedCloseObj w ?? w
where
f 0 = InitialPress
f _ = ShortPress