290 lines
10 KiB
Haskell
290 lines
10 KiB
Haskell
module Dodge.Humanoid where
|
|
|
|
import Data.Maybe
|
|
import Dodge.Creature.Action
|
|
import Dodge.Creature
|
|
import Dodge.Data.CreatureEffect
|
|
import Dodge.Data.World
|
|
import Geometry
|
|
import LensHelp
|
|
import RandomHelp
|
|
|
|
updateHumanoid :: Creature -> World -> World
|
|
updateHumanoid cr = case cr ^?! crType . humanoidAI of
|
|
ChaseAI ->
|
|
humanoidAIList
|
|
[ const doStrategyActions
|
|
, performActions
|
|
, const overrideMeleeCloseTarget
|
|
, setViewPos
|
|
, setMvPos
|
|
, chaseCritMv
|
|
, chaseCritPerceptionUpdate [0]
|
|
, targetYouWhenCognizant
|
|
, const searchIfDamaged
|
|
, const (crMeleeCooldown %~ max 0 . subtract 1)
|
|
, const (crVocalization . vcCoolDown %~ max 0 . subtract 1)
|
|
]
|
|
cr
|
|
SpreadGunAI ->
|
|
defaultImpulsive
|
|
[ performActions
|
|
, watchUpdateStrat
|
|
[
|
|
( crHasTargetLOS
|
|
, \_ _ ->
|
|
StrategyActions
|
|
(ShootAt 0)
|
|
[ DoActionIf (WdCrNegate $ WdCrBlfromCrBl CrIsAiming) drawWeapon
|
|
, DoActionThen
|
|
(DoActionWhile WdCrLOSTarget $ ArbitraryAction ChooseMovementSpreadGun)
|
|
(DoImpulses [ChangeStrategy WatchAndWait])
|
|
]
|
|
)
|
|
, (const crAwayFromPost, const goToPostStrat)
|
|
]
|
|
, perceptionUpdate [0]
|
|
, const doStrategyActions
|
|
, targetYouWhenCognizant
|
|
, const $
|
|
overrideInternal
|
|
(\cr' -> crHasTarget cr' && crStratConMatches (GetTo (V2 0 0)) cr')
|
|
(\cr' -> cr' & crActionPlan . apStrategy .~ WatchAndWait)
|
|
]
|
|
cr
|
|
PistolAI ->
|
|
defaultImpulsive
|
|
[ performActions
|
|
, watchUpdateStrat
|
|
[
|
|
( crHasTargetLOS
|
|
, \w cr' ->
|
|
StrategyActions
|
|
(ShootAt 0)
|
|
[DoActionIf (WdCrNegate $ WdCrBlfromCrBl CrIsAiming) drawWeapon, chooseMovementPistol cr' w]
|
|
)
|
|
, (const crAwayFromPost, const goToPostStrat)
|
|
]
|
|
, perceptionUpdate [0]
|
|
, const doStrategyActions
|
|
, targetYouWhenCognizant
|
|
, const $
|
|
overrideInternal
|
|
(\cr' -> crHasTarget cr' && crStratConMatches (GetTo (V2 0 0)) cr')
|
|
(crActionPlan . apStrategy .~ WatchAndWait)
|
|
]
|
|
cr
|
|
LtAutoAI ->
|
|
defaultImpulsive
|
|
[ performActions
|
|
, watchUpdateStrat
|
|
[
|
|
( crHasTargetLOS
|
|
, \_ _ ->
|
|
StrategyActions
|
|
(ShootAt 0)
|
|
[ DoActionIf (WdCrNegate $ WdCrBlfromCrBl CrIsAiming) drawWeapon
|
|
, DoActionThen
|
|
(DoActionWhile WdCrLOSTarget $ ArbitraryAction ChooseMovementLtAuto)
|
|
(DoImpulses [ChangeStrategy WatchAndWait])
|
|
]
|
|
)
|
|
, (const crAwayFromPost, const goToPostStrat)
|
|
]
|
|
, perceptionUpdate [0]
|
|
, const doStrategyActions
|
|
, targetYouWhenCognizant
|
|
, const $
|
|
overrideInternal
|
|
(\cr' -> crHasTarget cr' && crStratConMatches (GetTo (V2 0 0)) cr')
|
|
(crActionPlan . apStrategy .~ WatchAndWait)
|
|
]
|
|
cr
|
|
LauncherAI ->
|
|
defaultImpulsive
|
|
[ performActions
|
|
, watchUpdateStrat
|
|
[ (crHasTargetLOS, \_ _ -> StrategyActions (ShootAt 0) [retreatFireLauncher])
|
|
, (const crAwayFromPost, const goToPostStrat)
|
|
]
|
|
, perceptionUpdate [0]
|
|
, const doStrategyActions
|
|
, targetYouWhenCognizant
|
|
, const $
|
|
overrideInternal
|
|
(\cr' -> crHasTarget cr' && crStratConMatches (GetTo (V2 0 0)) cr')
|
|
(crActionPlan . apStrategy .~ WatchAndWait)
|
|
]
|
|
cr
|
|
SwarmAI ->
|
|
defaultImpulsive
|
|
[ flockToPointUsing' (encircleDistP 100) (meleeHeadingMove 0.1 0.1 (pi / 4) 3.9)
|
|
, const (crMeleeCooldown %~ max 0 . subtract 1)
|
|
, perceptionUpdate [0]
|
|
, const doStrategyActions
|
|
, targetYouWhenCognizant
|
|
]
|
|
cr
|
|
AutoAI -> defaultImpulsive [sentinelAI] cr
|
|
FlockArmourChaseAI ->
|
|
defaultImpulsive
|
|
[ watchUpdateStrat []
|
|
, const doStrategyActions
|
|
, performActions
|
|
, targetYouWhenCognizant
|
|
, setTargetMv (\_ -> _targetCr . _crIntention)
|
|
, flockACC
|
|
, perceptionUpdate [0]
|
|
, goToTarget
|
|
, const overrideMeleeCloseTarget
|
|
, const (crMeleeCooldown %~ max 0 . subtract 1)
|
|
]
|
|
cr
|
|
MiniGunAI -> defaultImpulsive [sentinelFireType (const shootTillEmpty)] cr
|
|
LongAI -> defaultImpulsive [sentinelFireType $ const shootTillEmpty] cr
|
|
MultGunAI ->
|
|
defaultImpulsive
|
|
[ sentinelExtraWatchUpdate
|
|
[
|
|
-- ( const $ not . crWeaponReady
|
|
-- , \_ _ -> StrategyActions Reload reloadActions
|
|
-- )
|
|
-- ,
|
|
( const $ not . crSafeDistFromTarg 150
|
|
, \_ _ ->
|
|
StrategyActions
|
|
Flee
|
|
[ WdCrNegate (WdCrSafeDistFromTarget 150) `DoActionWhile` UseSelf CrFleeFromTarget -- (fleeFrom cr')
|
|
`DoActionThen` DoImpulses [ChangeStrategy WatchAndWait]
|
|
]
|
|
)
|
|
,
|
|
( crHasTargetLOS
|
|
, \_ _ ->
|
|
StrategyActions
|
|
(ShootAt 0)
|
|
[drawwp `DoActionThen` shootFirstMiss `DoActionThen` DoImpulses [ChangeStrategy WatchAndWait]]
|
|
)
|
|
]
|
|
]
|
|
cr
|
|
YourAI -> stateUpdate yourControl cr
|
|
InanimateAI -> id
|
|
where
|
|
drawwp = DoActionIfElse NoAction (WdCrBlfromCrBl CrIsAiming) (DoActionThen drawWeapon (WaitThen 50 NoAction))
|
|
-- reloadActions =
|
|
-- [ holsterWeapon
|
|
-- --, WaitThen 1 $ DoActionWhileInterrupt NoAction (WdCrBlfromCrBl CrIsReloading) (DoImpulses [ChangeStrategy WatchAndWait])
|
|
-- , WaitThen 1 $ (DoImpulses [ChangeStrategy WatchAndWait])
|
|
-- ]
|
|
|
|
humanoidAIList ::
|
|
[World -> Creature -> Creature] ->
|
|
Creature ->
|
|
World ->
|
|
World
|
|
humanoidAIList
|
|
= stateUpdate . impulsiveAIBefore . chainCreatureUpdates
|
|
|
|
-- bit of a hack to get new random generators after each creature's update
|
|
defaultImpulsive ::
|
|
[World -> Creature -> Creature] ->
|
|
Creature ->
|
|
World ->
|
|
World
|
|
defaultImpulsive
|
|
= fmap (fmap updateRandGen) . stateUpdate . impulsiveAIBefore . chainCreatureUpdates
|
|
where
|
|
updateRandGen w =
|
|
let (_, g) = randomR (0, 1 :: Int) (_randGen w)
|
|
in w & randGen .~ g
|
|
|
|
chooseMovementPistol :: Creature -> World -> Action
|
|
chooseMovementPistol cr w =
|
|
chooseMovementPistol' cr w
|
|
`DoActionThen` DoImpulses [ChangeStrategy WatchAndWait]
|
|
|
|
chooseMovementPistol' :: Creature -> World -> Action
|
|
chooseMovementPistol' cr w =
|
|
takeOneWeighted
|
|
[chargeProb, retreatProb, strafeProb, strafeProb]
|
|
[ chargeActions
|
|
, retreatActionsPistol ycr cr
|
|
, strafeLeftActions
|
|
, strafeRightActions
|
|
]
|
|
& evalState
|
|
$ g
|
|
where
|
|
g = _randGen w
|
|
cpos = _crPos cr
|
|
ycr = w ^?! cWorld . lWorld . creatures . ix 0
|
|
ypos = _crPos ycr
|
|
chargeProb
|
|
| dist cpos ypos > 300 = 5
|
|
| dist cpos ypos > 150 = 1
|
|
| otherwise = 0
|
|
strafeProb
|
|
| dist cpos ypos > 150 = 1
|
|
| otherwise = 0
|
|
retreatProb
|
|
| dist cpos ypos < 200 = 1 :: Float
|
|
| otherwise = 0
|
|
chargeActions =
|
|
[TurnToward ypos 0.1]
|
|
`DoImpulsesAlongside` 3
|
|
`DoReplicate` ImpulsesList (replicate 9 [Move (V2 3 0)] ++ [[Move (V2 3 0), UseItem]])
|
|
strafeLeftActions =
|
|
DoImpulses [TurnToward yposr (2 * pi)]
|
|
`DoActionThen` 3
|
|
`DoReplicate` ImpulsesList (replicate 9 [Move (V2 0 3)] ++ [[Move (V2 0 3), UseItem]])
|
|
strafeRightActions =
|
|
DoImpulses [TurnToward yposl (2 * pi)]
|
|
`DoActionThen` 3
|
|
`DoReplicate` ImpulsesList (replicate 9 [Move (V2 0 (-3))] ++ [[Move (V2 0 (-3)), UseItem]])
|
|
yposl = ypos -.- 100 *.* vNormal (normalizeV $ ypos -.- cpos)
|
|
yposr = ypos +.+ 100 *.* vNormal (normalizeV $ ypos -.- cpos)
|
|
|
|
retreatActionsPistol :: Creature -> Creature -> Action
|
|
retreatActionsPistol tcr cr =
|
|
[TurnToward retreatOffset 0.2]
|
|
`DoImpulsesAlongside` 3
|
|
`DoReplicate` ImpulsesList (replicate 9 [Move (V2 (-3) 0)] ++ [[UseItem]])
|
|
where
|
|
cpos = _crPos cr
|
|
tpos = _crPos tcr
|
|
retreatOffset =
|
|
let a
|
|
| dist cpos tpos < 50 = 0
|
|
| isLeftOfA (_crDir cr) (argV $ tpos -.- cpos) =
|
|
-0.7
|
|
| otherwise = 0.7
|
|
in fromMaybe tpos $
|
|
intersectLineLine'
|
|
cpos
|
|
(cpos +.+ rotateV a (tpos -.- cpos))
|
|
tpos
|
|
(tpos +.+ vNormal (cpos -.- tpos))
|
|
|
|
retreatFireLauncher :: Action
|
|
retreatFireLauncher =
|
|
ImpulsesList ([UseItem] : replicate 20 [Turn 0.16])
|
|
`DoActionThen` holsterWeapon
|
|
`DoActionThen` ImpulsesList (replicate 30 [MoveForward 3])
|
|
`DoActionThen` drawWeapon
|
|
`DoActionThen` ImpulsesList ([UseItem] : replicate 20 [Turn $ negate 0.16])
|
|
`DoActionThen` holsterWeapon
|
|
`DoActionThen` ImpulsesList (replicate 15 [MoveForward 3])
|
|
`DoActionThen` drawWeapon
|
|
`DoActionThen` ImpulsesList
|
|
( replicate
|
|
100
|
|
[ UseItem
|
|
, ImpulseUseTarget (TurnTowardCr (pi / 16))
|
|
]
|
|
)
|
|
`DoActionThen` 20
|
|
`WaitThen` holsterWeapon
|
|
`DoActionThen` ImpulsesList (replicate 15 [MoveForward 3])
|
|
`DoActionThen` DoImpulses [ChangeStrategy WatchAndWait]
|