{- | Module testing for properties of creatures, whether they are reloading, etc. Each function takes a creature, and possibly other parameters, and returns a bool. Note that if there is a world parameter, the creature NEED NOT be the same as the creature with that id in the world, in fact a creature with that id need not exist. -} module Dodge.Creature.Test ( crIsAiming, crIsArmouredFrom, oneH, twists, twoFlat, crInAimStance, crNearPoint, isAnimate, crHasTargetLOS, crAwayFromPost, crHasTarget, crStratConMatches, crSafeDistFromTarg, hasAutoDoorBody, ) where import Linear import NewInt import qualified Data.IntMap.Strict as IM import Dodge.Creature.Radius import Dodge.Data.Equipment.Misc import Dodge.Data.AimStance import Control.Lens import Data.Maybe import Dodge.Base.Collide import Dodge.Data.World import Geometry --crIsReloading :: Creature -> Bool --crIsReloading cr = case cr ^? crManipulation . manObject . inInventory . iselAction of -- Just ReloadAction{} -> True -- _ -> False ---- Assumes the ammotype below the selected item is correct --crWeaponReady :: Creature -> Bool --crWeaponReady cr = fromMaybe False $ do -- i <- cr ^? crManipulation . manObject . inInventory . ispItem -- x <- cr ^? crInv . ix (i + 1) . itUse . amagLoadStatus . iaLoaded -- return (x > 0) crCanSeeCr :: Creature -> (World, Creature) -> Bool crCanSeeCr tcr (w, cr) = hasLOS (cr ^. crPos . _xy) (tcr ^. crPos . _xy) w --crCanSeeCrid :: Int -> (World, Creature) -> Bool --crCanSeeCrid tcid (w, cr) = fromMaybe False $ do -- tcr <- w ^? cWorld . lWorld . creatures . ix tcid -- return $ hasLOS (_crPos cr) (_crPos tcr) w crIsAiming :: Creature -> Bool crIsAiming cr = case _posture (_crStance cr) of Aiming {} -> True _ -> False crHasTarget :: Creature -> Bool crHasTarget cr = isJust $ cr ^? crIntention . targetCr . _Just crHasTargetLOS :: World -> Creature -> Bool crHasTargetLOS w cr = fromMaybe False $ do i <- cr ^. crIntention . targetCr tcr <- w ^? cWorld . lWorld . creatures . ix i return $ crCanSeeCr tcr (w, cr) crSafeDistFromTarg :: World -> Float -> Creature -> Bool crSafeDistFromTarg w d cr = fromMaybe True $ do i <- cr ^? crIntention . targetCr . _Just tcr <- w ^? cWorld . lWorld . creatures . ix i return $ dist (cr ^. crPos . _xy) (tcr ^. crPos . _xy) > d crStratConMatches :: Strategy -> Creature -> Bool crStratConMatches strat cr = strat == _apStrategy (_crActionPlan cr) -- this equality check might be slow... crAwayFromPost :: Creature -> Bool crAwayFromPost cr = case _apGoal $ _crActionPlan cr of SentinelAt p _ -> dist p (cr ^. crPos . _xy) > 15 _ -> False crInAimStance :: AimStance -> World -> Creature -> Bool crInAimStance as w cr = cr ^? crStance . posture == Just Aiming && w ^? hud . manObject . hiAimStance == Just as --revise1 && cr ^? crManipulation . manObject . imAimStance == Just as oneH :: World -> Creature -> Bool oneH = crInAimStance OneHand twoFlat :: World -> Creature -> Bool twoFlat = crInAimStance TwoHandFlat twists :: World -> Creature -> Bool twists = crInAimStance TwoHandTwist -- the use of crOldPos is because the damage position is calculated on the -- previous frame -- Not sure if it is a good idea crIsArmouredFrom :: IM.IntMap Item -> Point2 -> World -> Creature -> Bool crIsArmouredFrom m p w cr = fromMaybe False $ do NInt itid <- cr ^? crEquipment . ix OnChest ittype <- m ^? ix itid . itType return $ EQUIP FRONTARMOUR == ittype && p /= ( cr ^. crOldPos . _xy) && angleVV (unitVectorAtAngle (_crDir cr + frontarmdirection)) (p -.- (cr ^. crOldPos . _xy)) < pi / 2 where -- even though angleVV can generate NaN, the comparison seems to deal with it frontarmdirection | crInAimStance OneHand w cr = 0.5 | crInAimStance TwoHandTwist w cr = negate 1 | otherwise = 0 --crOnSeg :: Point2 -> Point2 -> Creature -> Bool --crOnSeg p1 p2 cr = circOnSeg p1 p2 (_crPos cr) (_crRad cr) --crNearSeg :: Float -> Point2 -> Point2 -> Creature -> Bool --crNearSeg d p1 p2 cr = circOnSeg p1 p2 (_crPos cr) (_crRad cr + d) crNearPoint :: Float -> Point2 -> Creature -> Bool crNearPoint d p cr = dist (cr ^. crPos . _xy) p < d + crRad (cr ^. crType) isAnimate :: Creature -> Bool {-# INLINE isAnimate #-} isAnimate cr = case _crActionPlan cr of Inanimate -> False SlimeIntelligence -> True ActionPlan{} -> True hasAutoDoorBody :: Creature -> Bool hasAutoDoorBody cr = crittype && notdestroyed where notdestroyed = case cr ^. crHP of HP {} -> True CrIsCorpse {} -> True AvatarDestroyed {} -> False crittype = case cr ^. crType of SlimeCrit {} -> False BeeCrit {} -> False HiveCrit {} -> False _ -> True