{-# 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 LASER -> 1 _ -> 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 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