Files
loop/src/Dodge/Creature/Test.hs
T

148 lines
4.6 KiB
Haskell

{- |
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,
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.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 (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 find sentinelGoal . _apGoal $ _crActionPlan cr of
Just (SentinelAt p _) -> dist p (cr ^. crPos . _xy) > 15
_ -> False
where
sentinelGoal (SentinelAt _ _) = True
sentinelGoal _ = False
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 /= ( 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 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 (cr ^. crPos . _xy) p < d + crRad (cr ^. crType)
isAnimate :: Creature -> Bool
{-# INLINE isAnimate #-}
isAnimate cr = case _crActionPlan cr of
Inanimate -> False
_ -> True
hasAutoDoorBody :: Creature -> Bool
hasAutoDoorBody cr = case cr ^. crHP of
HP {} -> True
CrIsCorpse {} -> True
CrIsGibs -> False
CrIsPitted -> False