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