Work on slime crit split/combining

This commit is contained in:
2026-04-15 20:54:26 +01:00
parent 02e26c368c
commit c3d9a24735
11 changed files with 430 additions and 583 deletions
+3 -1
View File
@@ -66,11 +66,13 @@ slimeCrit :: Creature
slimeCrit = defaultCreature
& crName .~ "slimeCrit"
& crHP .~ HP 1000
& crType .~ SlimeCrit 40 0 0 (V2 50 0) False True
& crType .~ SlimeCrit r 0 0 (V2 r 0) False
& crFaction .~ ColorFaction (light green)
& crPerception . cpVision . viFOV .~ FloatFOV pi
& crActionPlan .~ SlimeIntelligence
& crStance . carriage .~ Crawling
where
r = 50
hoverCrit :: Creature
hoverCrit =
-20
View File
@@ -1,20 +0,0 @@
module Dodge.Creature.LtAutoCrit (
ltAutoCrit,
) where
--import Control.Lens
import Dodge.Data.Creature
import Dodge.Default
--import Dodge.Item.Held.Stick
--import qualified IntMapHelp as IM
--import Picture
ltAutoCrit :: Creature
ltAutoCrit =
defaultCreature
{ --_crInv = IM.fromList [(0, autoPistol)]
_crHP = HP 500
}
-- & crType .~ LtAutoCrit
-- & crType . humanoidAI .~ LtAutoAI
-- & crType . skinUpper .~ lightx4 red
-135
View File
@@ -1,135 +0,0 @@
module Dodge.Creature.SentinelAI (
sentinelAI,
sentinelFireType,
sentinelExtraWatchUpdate,
) where
--import Control.Lens
import Data.Maybe
--import Dodge.Creature.Action
--import Dodge.Creature.ChainUpdates
--import Dodge.Creature.Perception
--import Dodge.Creature.ReaderUpdate
--import Dodge.Creature.Strategy
import Dodge.Creature.Test
import Dodge.Creature.Volition
import Dodge.Data.CreatureEffect
import Dodge.Data.World
import Geometry.Data
sentinelAI :: World -> Creature -> Creature
--sentinelAI w =
sentinelAI =
sentinelExtraWatchUpdate
[
( crHasTargetLOS
, \_ cr ->
StrategyActions
(ShootAt (fromJust $ tcid cr))
[ DoActionIf
(WdCrNegate $ WdCrBlfromCrBl CrIsAiming)
(drawWeapon `DoActionThen` (50 `WaitThen` NoAction))
`DoActionThen` lostest
`DoActionWhile` advanceShoot
`DoActionThen` 75
`DoReplicate` advanceShoot
`DoActionThen` DoImpulses [ChangeStrategy WatchAndWait]
, AimAt{_targetID = fromJust $ tcid cr, _targetSeenAt = V2 0 0}
]
)
]
where
advanceShoot = DoImpulses [UseItem, MoveForward 3]
tcid cr = _targetCr (_crIntention cr)
lostest = WdCrLOSTarget -- w' cr = maybe False (\cid -> canSee (_crID cr) cid w') (tcid cr)
--chainCreatureUpdates :: [World -> Creature -> Creature] -> World -> Creature -> Creature
--chainCreatureUpdates ls w cr = foldr (\f -> f w) cr ls
sentinelFireType :: (Int -> Action) -> World -> Creature -> Creature
sentinelFireType _ = undefined
--sentinelFireType f =
-- chainCreatureUpdates
-- [ watchUpdateStrat
-- [
-- ( crHasTargetLOS
-- , \_ _ ->
-- StrategyActions
-- (ShootAt 0)
-- [ drawwp `DoActionThen` f 0 `DoActionThen` DoImpulses [ChangeStrategy WatchAndWait]
-- , aiming
-- ]
-- )
-- , (const crAwayFromPost, const goToPostStrat)
-- ]
-- , perceptionUpdate [0]
-- , -- , Left $ perceptionUp 0
-- const doStrategyActions
-- , targetYouWhenCognizant
-- , const $
-- overrideInternal
-- (\cr -> crHasTarget cr && crStratConMatches (GetTo (V2 0 0)) cr)
-- (crActionPlan . apStrategy .~ WatchAndWait)
-- ]
-- where
-- drawwp = DoActionIfElse NoAction (WdCrBlfromCrBl CrIsAiming) (DoActionThen drawWeapon (WaitThen 50 NoAction))
-- aiming =
-- AimAt
-- { _targetID = 0
-- , _targetSeenAt = V2 0 0 -- hack
-- }
sentinelExtraWatchUpdate ::
[(World -> Creature -> Bool, World -> Creature -> Strategy)] ->
World ->
Creature ->
Creature
sentinelExtraWatchUpdate _ = undefined
--sentinelExtraWatchUpdate xs =
-- chainCreatureUpdates
-- [ watchUpdateStrat
-- (xs ++ [(const crAwayFromPost, const goToPostStrat)])
-- , perceptionUpdate [0]
-- , const doStrategyActions
-- , targetYouWhenCognizant
-- , const $
-- overrideInternal
-- (\cr -> crHasTarget cr && crStratConMatches (GetTo (V2 0 0)) cr)
-- (crActionPlan . apStrategy .~ WatchAndWait)
-- ]
--shootAtAdvance :: Int -> [Action]
--shootAtAdvance tcid =
-- [ DoActionIfElse NoAction crIsAiming (DoActionThen drawWeapon (WaitThen 50 NoAction))
-- `DoActionThen`
-- lostest `DoActionWhile`
-- advanceShoot `DoActionThen`
-- 75 `DoReplicate`
-- advanceShoot `DoActionThen`
-- DoImpulses [ChangeStrategy WatchAndWait]
-- , AimAt
-- { _targetID = tcid
-- , _targetSeenAt = V2 0 0 -- hack
-- }
-- ]
-- where
-- lostest (w,cr') = canSee (_crID cr') tcid w
-- advanceShoot = ImpulsesList [[UseItem, MoveForward 3]]
--
--shootAtWhileContinueTime :: Int -> World -> Creature -> Strategy
--shootAtWhileContinueTime tcid _ _ = StrategyActions (ShootAt tcid)
-- [ DoActionIfElse NoAction crIsAiming (DoActionThen drawWeapon (WaitThen 50 NoAction))
-- `DoActionThen`
-- lostest `DoActionWhile`
-- advanceShoot `DoActionThen`
-- 75 `DoReplicate`
-- advanceShoot `DoActionThen`
-- DoImpulses [ChangeStrategy WatchAndWait]
-- , AimAt
-- { _targetID = tcid
-- , _targetSeenAt = V2 0 0 -- hack
-- }
-- ]
-- where
-- lostest (w,cr') = canSee (_crID cr') tcid w
-- advanceShoot = ImpulsesList [[UseItem, MoveForward 3]]
+44 -43
View File
@@ -2,7 +2,7 @@
module Dodge.Creature.Update (updateCreature) where
import Dodge.WorldEvent.ThingsHit
--import Dodge.WorldEvent.ThingsHit
import Color
import Control.Monad
import qualified IntMapHelp as IM
@@ -78,47 +78,48 @@ slimeCritUpdate cid w
let cid' = IM.newKey $ w ^. cWorld . lWorld . creatures
in w & cWorld . lWorld . creatures . ix cid .~ cr1
& cWorld . lWorld . creatures . at cid' ?~ (cr2 & crID .~ cid')
| (cr ^?! crType . slimeIsCompressing) && r > norm p
= let (w',g) = runState (setSlimeDir cid (cr & crDamage .~ []) w) (w ^. randGen)
in w' & randGen .~ g
| otherwise = updateCarriage cid $ w
& cWorld . lWorld . creatures . ix cid .~ mvslime
& cWorld . lWorld . creatures . ix cid . crDamage .~ []
& cWorld . lWorld . creatures . ix cid . crDir .~ d
& cWorld . lWorld . creatures . ix cid . crType . slimeResetDir .~ rb'
& randGen .~ g
& cWorld . lWorld . creatures . ix cid %~ doSlimeRadChange
& tocr %~ doSlimeRadChange
& tocr . crType . slimeSplitTimer %~ (max 0 . subtract 1)
where
txy = w ^?! cWorld . lWorld . creatures . ix 0 . crPos . _xy
tocr = cWorld . lWorld . creatures . ix cid
cr = w ^?! cWorld . lWorld . creatures . ix cid
cxy = cr ^. crPos . _xy
rb = cr ^?! crType . slimeResetDir
(d,rb',g)
| isWalkable cxy txy w && distance cxy txy < 50 + r
, rb == cr ^?! crType . slimeIsCompressing
= (argV (txy-cxy), rb, w ^. randGen)
| abs (norm p - r) < 0.1
, rb == cr ^?! crType . slimeIsCompressing
= let (d',g') = randomR (0, 2* pi) (w ^. randGen)
in (d',not rb, g')
| otherwise = (cr ^. crDir, rb, w ^. randGen)
mvslime = cr & crType . slimeCompression .~ p' + x
-- & crPos . _xy +~ 0.1 *^ normalize (txy-cxy)
& crPos . _xy +~ 0.1 *^ unitVectorAtAngle d
& crType . slimeIsCompressing %~ (f . f')
-- g | cr ^?! crType . slimeIsCompressing = negate
-- | otherwise = id
s | cr ^?! crType . slimeIsCompressing = 2/3
| otherwise = 1.5
f | abs (norm v - norm p') < 0.2 = not
v = 0.1 *^ normalize p
mvslime = cr & crType . slimeCompression +~ f v
& crPos . _xy +~ v
& crType . slimeIsCompressing %~ f'
f | t = negate
| otherwise = id
v = (s * r) *^ unitVectorAtAngle (cr ^. crDir)
--r = crRad (cr ^. crType)
f' | norm p > 3*r/2 = const True
| otherwise = id
t = cr ^?! crType . slimeIsCompressing
r = cr ^?! crType . slimeRad
p = cr ^?! crType . slimeCompression
(p',f')
| dot p v > 0 && dot p v > dot p (vNormal v) && dot p v > dot p (-vNormal v) = (p, id)
| dot p (-v) > dot p (vNormal v) && dot p (-v) > dot p (-vNormal v) = (-p, id)
| dot p (vNormal v) > dot p (-vNormal v) = ((r*r/norm p) *^ normalize (vNormal p), not)
| otherwise = (-(r*r/norm p) *^ normalize (vNormal p), not)
x = 0.1 *^ normalize (v - p')
setSlimeDir :: Int -> Creature -> World -> State StdGen World
setSlimeDir cid cr w = do
i <- state $ randomR (0,1)
d <- state $ randomR (0,2*pi)
if i < (r - 11) / 50
then do
x <- randInCirc 1
let (cr1,cr2) = splitSlimeCrit (x + cxy) (unitVectorAtAngle d) cr ^?! _Just
cid' = IM.newKey $ w ^. cWorld . lWorld . creatures
return $ w & tocr .~ cr1
& tocr' cid' ?~ (cr2 & crID .~ cid')
else return $ w & tocr . crType . slimeCompression .~ r *^ unitVectorAtAngle d
& tocr . crType . slimeIsCompressing .~ False
where
tocr = cWorld . lWorld . creatures . ix cid
tocr' i = cWorld . lWorld . creatures . at i
cxy = cr ^. crPos . _xy
r = cr ^?! crType . slimeRad
doSlimeRadChange :: Creature -> Creature
doSlimeRadChange = crType . slimeRadWobble %~ f
@@ -136,23 +137,23 @@ splitSlimeCrit p v cr = do
a2 = pi*r*r - a1
r1 = sqrt (a1/pi)
r2 = sqrt (a2/pi)
-- guard $ r1 > 5 && r2 > 5
return (cr' & crPos . _xy .~ mp + (r1 + 0.5) *^ normalize (mp - cxy)
mvdir = normalize (vNormal v)
return (cr' & crPos . _xy .~ mp + (r1 + 0.51) *^ mvdir
& crType . slimeRad .~ r1
& crType . slimeCompression .~ rotateV (argV (mp-cxy)) (V2 r1 0)
& crDir .~ argV (mp - cxy)
& crType . slimeResetDir .~ not (cr ^?! crType . slimeIsCompressing)
,cr' & crPos . _xy .~ mp - (r2 + 0.5) *^ normalize (mp - cxy)
& crType . slimeCompression .~ rotateV (argV mvdir) (V2 r1 0)
& crDir .~ argV mvdir
,cr' & crPos . _xy .~ mp - (r2 + 0.51) *^ normalize mvdir
& crType . slimeRad .~ r2
& crType . slimeCompression .~ rotateV (argV (cxy-mp)) (V2 r2 0)
& crDir .~ argV (cxy - mp)
& crType . slimeResetDir .~ not (cr ^?! crType . slimeIsCompressing)
& crType . slimeCompression .~ rotateV (argV (-mvdir)) (V2 r2 0)
& crDir .~ argV (-mvdir)
)
where
cxy = cr ^. crPos . _xy
r = cr ^?! crType . slimeRad
cr' = cr & crDamage .~ []
& crType . slimeRadWobble .~ 0
& crType . slimeSplitTimer .~ 10
& crType . slimeIsCompressing .~ False
-- h is the height of the segment, ie r - distance to center
segmentArea :: Float -> Float -> Float