Files
loop/src/Dodge/Creature/ReaderUpdate.hs
T
2021-09-09 13:29:09 +01:00

167 lines
5.7 KiB
Haskell

{- | Functions updating a creature in a Reader World environment -}
module Dodge.Creature.ReaderUpdate
( doStrategyActionsR
, setTargetMv
, targetYouWhenCognizantR
, overrideMeleeCloseTargetR
, watchUpdateStratR
, reloadOverrideR
, overrideInternalRRR
, goToTarget
, flockACCR
, setMvPos
, setViewPos
)
where
import Dodge.Data
import Dodge.Creature.Stance.Data
import Dodge.Creature.Memory.Data
import Dodge.Creature.Test
import Dodge.Creature.Volition
import Dodge.Creature.Perception.Data
import Dodge.Base
import Dodge.Base.Collide
import Geometry
import FoldableHelp
import qualified Data.IntMap.Strict as IM
import Control.Monad.Reader
import Control.Lens
import Control.Applicative
import Data.Maybe
overrideMeleeCloseTargetR
:: Creature
-> Reader World Creature
overrideMeleeCloseTargetR cr = return $ maybe cr (tryMeleeAttack cr) (_targetCr $ _crIntention cr)
tryMeleeAttack :: Creature -> Creature -> Creature
tryMeleeAttack cr tcr
| _crMeleeCooldown cr == 0
&& dist (_crPos tcr) cpos < _crRad cr + _crRad tcr + 5
&& abs (_crDir cr - argV (_crPos tcr -.- cpos)) < pi/4
-- = cr & crActionPlan . crStrategy .~ StrategyActions MeleeStrike meleeActions
= cr & crActionPlan . crImpulse .~ [Melee $ _crID tcr]
| otherwise = cr
where
cpos = _crPos cr
setMvPos :: Creature -> Reader World Creature
setMvPos cr = pure $ cr & crIntention . mvToPoint .~ mpos
where
int = _crIntention cr
mpos = (_crPos <$> _targetCr int)
<|> _mvToPoint int
-- <|> listToMaybe (_soundsToInvestigate $ _crMemory cr)
setViewPos :: Creature -> Reader World Creature
setViewPos cr = pure $ cr & crIntention . viewPoint %~ (<|> mpos)
where
mpos = listToMaybe (_soundsToInvestigate $ _crMemory cr)
setTargetMv
:: (Creature -> Reader World (Maybe Creature)) -- ^ Function for determining target
-> Creature
-> Reader World Creature
setTargetMv targFunc cr = do
targ <- targFunc cr
case targ of
Nothing -> pure cr
Just crTarg -> pure $ cr & crIntention . mvToPoint ?~ _crPos crTarg
flockACCR :: Creature -> Reader World Creature
flockACCR cr = do
case cr ^? crIntention . targetCr . _Just of
Nothing -> pure cr
Just tcr -> do
w <- ask
let tpos = _crPos tcr
cpos = _crPos cr
isFarACC cr' = _crGroup cr' == _crGroup cr
&& _crID cr' /= _crID cr
&& dist (_crPos cr') tpos > dist cpos tpos
nearACCs = IM.filter isFarACC $ creaturesNearPointI 5 cpos w
macr = safeMinimumOn (dist cpos . _crPos) nearACCs
case macr of
Nothing -> pure cr
Just acr -> do
let r = _crRad acr + _crRad cr + 10
horDir = normalizeV (vNormal (cpos -.- tpos))
horShift = if isLHS tpos cpos (_crPos acr)
then r *.* horDir
else negate r *.* horDir
pure $ cr & crIntention . mvToPoint ?~ tpos +.+ horShift
goToTarget :: Creature -> Reader World Creature
goToTarget cr = do
case cr ^? crIntention . mvToPoint . _Just of
Just p -> pure $ cr & crActionPlan . crAction .~ [PathTo p]
_ -> viewTarget cr
viewTarget :: Creature -> Reader World Creature
viewTarget cr = do
w <- ask
case cr ^? crIntention . viewPoint . _Just of
Just p | hasLOSIndirect p (_crPos cr) w -> pure $ cr'
& crActionPlan . crAction %~ replaceNullWith (TurnToA p)
& crIntention . viewPoint .~ Nothing
| otherwise -> pure $ cr' & crActionPlan . crAction %~ replaceNullWith (PathTo p)
Nothing -> pure $ cr & crPerception . crAwakeLevel .~ Lethargic
where
cr' = cr & crPerception . crAwakeLevel .~ Vigilant
replaceNullWith :: a -> [a] -> [a]
replaceNullWith x [] = [x]
replaceNullWith _ xs = xs
doStrategyActionsR
:: Creature
-> Reader World Creature
doStrategyActionsR cr = return $ case cr ^? crActionPlan . crStrategy of
Just (StrategyActions strat acs) -> cr & crActionPlan . crAction .~ acs
& crActionPlan . crStrategy .~ strat
_ -> cr
reloadOverrideR
:: Creature
-> Reader World Creature
reloadOverrideR cr
| cr ^? crInv . ix (_crInvSel cr) . wpLoadedAmmo == Just 0
&& cr ^. crStance . posture == Aiming
= return $ cr & crActionPlan . crStrategy .~ StrategyActions Reload reloadActions
| otherwise = return cr
where
reloadActions =
[ holsterWeapon
, WaitThen 1 $ DoActionWhileInterrupt NoAction crIsReloading (DoImpulses [ChangeStrategy WatchAndWait])
]
overrideInternalRRR
:: (Creature -> Reader World Bool)
-> (Creature -> Reader World Creature)
-> Creature
-> Reader World Creature
overrideInternalRRR test update cr = do
b <- test cr
if b then update cr else pure cr
watchUpdateStratR
:: [ ((World, Creature) -> Bool, World -> Creature -> Strategy) ]
-> Creature
-> Reader World Creature
watchUpdateStratR fs cr = reader $ \w -> case cr ^? crActionPlan . crStrategy of
Just WatchAndWait -> cr
& crActionPlan . crStrategy .~ listGuard (fs, \_ _ -> WatchAndWait) (w, cr) w cr
_ -> cr
listGuard :: ([(a -> Bool, b)] , b) -> a -> b
listGuard ( (test,y):ps, z ) x
| test x = y
| otherwise = listGuard (ps, z) x
listGuard (_,z) _ = z
targetYouWhenCognizantR :: Creature -> Reader World Creature
targetYouWhenCognizantR cr = reader $ \w -> case cr ^? crPerception . crAwarenessLevel . ix 0 of
Just (Cognizant _) -> cr & crIntention . targetCr ?~ _creatures w IM.! 0
_ -> cr & crIntention . targetCr .~ Nothing