{- | 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, -- crIsReloading, crIsArmouredFrom, oneH, twists, twoFlat, -- crWeaponReady, crInAimStance, crNearPoint, isAnimate, -- crCanShoot, crHasTargetLOS, crAwayFromPost, crHasTarget, crStratConMatches, crSafeDistFromTarg, ) where import NewInt import qualified Data.IntMap.Strict as IM import Dodge.Item.Grammar import Dodge.Creature.Radius import Dodge.Data.Equipment.Misc import Dodge.Data.AimStance import Dodge.Item.AimStance import Control.Lens import Data.List (find) 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 (_crPos cr) (_crPos tcr) 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 = case cr ^? crIntention . targetCr . _Just of Just i -> crCanSeeCr i (w, cr) Nothing -> False crSafeDistFromTarg :: Float -> Creature -> Bool crSafeDistFromTarg d cr = case cr ^? crIntention . targetCr . _Just of Just tcr -> dist (_crPos cr) (_crPos tcr) > d Nothing -> True crStratConMatches :: Strategy -> Creature -> Bool crStratConMatches strat cr = strat == _apStrategy (_crActionPlan cr) -- this equality check might be slow... crAwayFromPost :: Creature -> Bool crAwayFromPost cr = case find sentinelGoal . _apGoal $ _crActionPlan cr of Just (SentinelAt p _) -> dist p (_crPos cr) > 15 _ -> False where sentinelGoal (SentinelAt _ _) = True sentinelGoal _ = False --crCanShoot :: Creature -> Bool --crCanShoot cr = crIsAiming cr && crWeaponReady cr crInAimStance :: AimStance -> Creature -> Bool crInAimStance as cr = cr ^? crStance . posture . aimStance == Just as oneH :: Creature -> Bool oneH = crInAimStance OneHand twoFlat :: Creature -> Bool twoFlat = crInAimStance TwoHandFlat twists :: Creature -> Bool twists cr = crInAimStance TwoHandUnder cr || crInAimStance TwoHandOver cr -- 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 -> Creature -> Bool crIsArmouredFrom m p cr = fromMaybe False $ do NInt itid <- cr ^? crEquipment . ix OnChest ittype <- m ^? ix itid . itType return $ EQUIP FRONTARMOUR == ittype && p /= _crOldPos cr && angleVV (unitVectorAtAngle (_crDir cr + frontarmdirection)) (p -.- _crOldPos cr) < pi / 2 where -- even though angleVV can generate NaN, the comparison seems to deal with it frontarmdirection | crInAimStance OneHand cr = 0.5 | crInAimStance TwoHandUnder cr = negate 1 | crInAimStance TwoHandOver 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 (_crPos cr) p < d + crRad (cr ^. crType) isAnimate :: Creature -> Bool {-# INLINE isAnimate #-} isAnimate cr = case _crActionPlan cr of Inanimate -> False _ -> True