module Game.LambdaHack.Server.HandleRequestM
( handleRequestAI, handleRequestUI, handleRequestTimed, switchLeader
, reqMoveGeneric, reqDisplaceGeneric, reqAlterFail
, reqGameDropAndExit, reqGameSaveAndExit
#ifdef EXPOSE_INTERNAL
, execFailure, checkWaiting, processWatchfulness, affectStash
, managePerRequest, handleRequestTimedCases, affectSmell
, reqMove, reqMelee, reqMeleeChecked, reqDisplace, reqAlter
, reqWait, reqWait10, reqYell, reqMoveItems, reqMoveItem, reqProject, reqApply
, reqGameRestart, reqGameSave, reqDoctrine, reqAutomate
#endif
) where
import Prelude ()
import Game.LambdaHack.Core.Prelude
import qualified Data.EnumMap.Strict as EM
import qualified Data.Text as T
import qualified Text.Show.Pretty as Show.Pretty
import Game.LambdaHack.Atomic
import Game.LambdaHack.Client
(ReqAI (..), ReqUI (..), RequestTimed (..))
import Game.LambdaHack.Common.Actor
import Game.LambdaHack.Common.ActorState
import Game.LambdaHack.Common.Analytics
import Game.LambdaHack.Common.Faction
import Game.LambdaHack.Common.Item
import qualified Game.LambdaHack.Common.ItemAspect as IA
import Game.LambdaHack.Common.Kind
import Game.LambdaHack.Common.Level
import Game.LambdaHack.Common.Misc
import Game.LambdaHack.Common.MonadStateRead
import Game.LambdaHack.Common.Point
import Game.LambdaHack.Common.ReqFailure
import Game.LambdaHack.Common.State
import qualified Game.LambdaHack.Common.Tile as Tile
import Game.LambdaHack.Common.Time
import Game.LambdaHack.Common.Types
import Game.LambdaHack.Common.Vector
import Game.LambdaHack.Content.FactionKind
import qualified Game.LambdaHack.Content.ItemKind as IK
import Game.LambdaHack.Content.ModeKind
import qualified Game.LambdaHack.Content.TileKind as TK
import qualified Game.LambdaHack.Definition.Ability as Ability
import Game.LambdaHack.Definition.Defs
import Game.LambdaHack.Server.CommonM
import Game.LambdaHack.Server.HandleEffectM
import Game.LambdaHack.Server.ItemM
import Game.LambdaHack.Server.MonadServer
import Game.LambdaHack.Server.PeriodicM
import Game.LambdaHack.Server.ServerOptions
import Game.LambdaHack.Server.State
execFailure :: MonadServerAtomic m
=> ActorId -> RequestTimed -> ReqFailure -> m ()
execFailure :: forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> RequestTimed -> ReqFailure -> m ()
execFailure ActorId
aid RequestTimed
req ReqFailure
failureSer = do
body <- (State -> Actor) -> m Actor
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> Actor) -> m Actor) -> (State -> Actor) -> m Actor
forall a b. (a -> b) -> a -> b
$ ActorId -> State -> Actor
getActorBody ActorId
aid
let fid = Actor -> FactionId
bfid Actor
body
msg = ReqFailure -> Text
showReqFailure ReqFailure
failureSer
impossible = ReqFailure -> Bool
impossibleReqFailure ReqFailure
failureSer
debugShow :: Show a => a -> Text
debugShow = String -> Text
T.pack (String -> Text) -> (a -> String) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
Show.Pretty.ppShow
possiblyAlarm = if Bool
impossible
then Text -> m ()
forall (m :: * -> *). MonadServer m => Text -> m ()
debugPossiblyPrintAndExit
else Text -> m ()
forall (m :: * -> *). MonadServer m => Text -> m ()
debugPossiblyPrint
possiblyAlarm $
"Server: execFailure:" <+> msg <> "\n"
<> debugShow body <> "\n" <> debugShow req <> "\n" <> debugShow failureSer
execSfxAtomic $ SfxMsgFid fid $ SfxUnexpected failureSer
handleRequestAI :: MonadServerAtomic m
=> ReqAI
-> m (Maybe RequestTimed)
handleRequestAI :: forall (m :: * -> *).
MonadServerAtomic m =>
ReqAI -> m (Maybe RequestTimed)
handleRequestAI ReqAI
cmd = case ReqAI
cmd of
ReqAITimed RequestTimed
cmdT -> Maybe RequestTimed -> m (Maybe RequestTimed)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe RequestTimed -> m (Maybe RequestTimed))
-> Maybe RequestTimed -> m (Maybe RequestTimed)
forall a b. (a -> b) -> a -> b
$ RequestTimed -> Maybe RequestTimed
forall a. a -> Maybe a
Just RequestTimed
cmdT
ReqAI
ReqAINop -> Maybe RequestTimed -> m (Maybe RequestTimed)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe RequestTimed
forall a. Maybe a
Nothing
handleRequestUI :: MonadServerAtomic m
=> FactionId -> ActorId -> ReqUI
-> m (Maybe RequestTimed)
handleRequestUI :: forall (m :: * -> *).
MonadServerAtomic m =>
FactionId -> ActorId -> ReqUI -> m (Maybe RequestTimed)
handleRequestUI FactionId
fid ActorId
aid ReqUI
cmd = case ReqUI
cmd of
ReqUITimed RequestTimed
cmdT -> Maybe RequestTimed -> m (Maybe RequestTimed)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe RequestTimed -> m (Maybe RequestTimed))
-> Maybe RequestTimed -> m (Maybe RequestTimed)
forall a b. (a -> b) -> a -> b
$ RequestTimed -> Maybe RequestTimed
forall a. a -> Maybe a
Just RequestTimed
cmdT
ReqUIGameRestart GroupName ModeKind
t Challenge
d -> ActorId -> GroupName ModeKind -> Challenge -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> GroupName ModeKind -> Challenge -> m ()
reqGameRestart ActorId
aid GroupName ModeKind
t Challenge
d m () -> m (Maybe RequestTimed) -> m (Maybe RequestTimed)
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Maybe RequestTimed -> m (Maybe RequestTimed)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe RequestTimed
forall a. Maybe a
Nothing
ReqUI
ReqUIGameDropAndExit -> ActorId -> m ()
forall (m :: * -> *). MonadServerAtomic m => ActorId -> m ()
reqGameDropAndExit ActorId
aid m () -> m (Maybe RequestTimed) -> m (Maybe RequestTimed)
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Maybe RequestTimed -> m (Maybe RequestTimed)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe RequestTimed
forall a. Maybe a
Nothing
ReqUI
ReqUIGameSaveAndExit -> ActorId -> m ()
forall (m :: * -> *). MonadServerAtomic m => ActorId -> m ()
reqGameSaveAndExit ActorId
aid m () -> m (Maybe RequestTimed) -> m (Maybe RequestTimed)
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Maybe RequestTimed -> m (Maybe RequestTimed)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe RequestTimed
forall a. Maybe a
Nothing
ReqUI
ReqUIGameSave -> m ()
forall (m :: * -> *). MonadServer m => m ()
reqGameSave m () -> m (Maybe RequestTimed) -> m (Maybe RequestTimed)
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Maybe RequestTimed -> m (Maybe RequestTimed)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe RequestTimed
forall a. Maybe a
Nothing
ReqUIDoctrine Doctrine
toT -> FactionId -> Doctrine -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
FactionId -> Doctrine -> m ()
reqDoctrine FactionId
fid Doctrine
toT m () -> m (Maybe RequestTimed) -> m (Maybe RequestTimed)
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Maybe RequestTimed -> m (Maybe RequestTimed)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe RequestTimed
forall a. Maybe a
Nothing
ReqUI
ReqUIAutomate -> FactionId -> m ()
forall (m :: * -> *). MonadServerAtomic m => FactionId -> m ()
reqAutomate FactionId
fid m () -> m (Maybe RequestTimed) -> m (Maybe RequestTimed)
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Maybe RequestTimed -> m (Maybe RequestTimed)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe RequestTimed
forall a. Maybe a
Nothing
ReqUI
ReqUINop -> Maybe RequestTimed -> m (Maybe RequestTimed)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe RequestTimed
forall a. Maybe a
Nothing
checkWaiting :: RequestTimed -> Maybe Bool
checkWaiting :: RequestTimed -> Maybe Bool
checkWaiting RequestTimed
cmd = case RequestTimed
cmd of
RequestTimed
ReqWait -> Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
True
RequestTimed
ReqWait10 -> Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
False
RequestTimed
_ -> Maybe Bool
forall a. Maybe a
Nothing
processWatchfulness :: MonadServerAtomic m => Maybe Bool -> ActorId -> m ()
processWatchfulness :: forall (m :: * -> *).
MonadServerAtomic m =>
Maybe Bool -> ActorId -> m ()
processWatchfulness Maybe Bool
mwait ActorId
aid = do
b <- (State -> Actor) -> m Actor
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> Actor) -> m Actor) -> (State -> Actor) -> m Actor
forall a b. (a -> b) -> a -> b
$ ActorId -> State -> Actor
getActorBody ActorId
aid
actorMaxSk <- getsState $ getActorMaxSkills aid
let uneasy = ResDelta -> Bool
deltasSerious (Actor -> ResDelta
bcalmDelta Actor
b) Bool -> Bool -> Bool
|| Bool -> Bool
not (Actor -> Skills -> Bool
calmEnough Actor
b Skills
actorMaxSk)
case bwatch b of
Watchfulness
WWatch ->
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Maybe Bool
mwait Maybe Bool -> Maybe Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
True) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
if Skill -> Skills -> Int
Ability.getSk Skill
Ability.SkWait Skills
actorMaxSk Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
2 then do
Bool -> GroupName ItemKind -> ActorId -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
Bool -> GroupName ItemKind -> ActorId -> m ()
addCondition Bool
False GroupName ItemKind
IK.S_BRACED ActorId
aid
UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId -> Watchfulness -> Watchfulness -> UpdAtomic
UpdWaitActor ActorId
aid Watchfulness
WWatch (Int -> Watchfulness
WWait Int
1)
else
UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId -> Watchfulness -> Watchfulness -> UpdAtomic
UpdWaitActor ActorId
aid Watchfulness
WWatch (Int -> Watchfulness
WWait Int
0)
WWait Int
0 -> case Maybe Bool
mwait of
Just Bool
True -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Maybe Bool
_ -> UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId -> Watchfulness -> Watchfulness -> UpdAtomic
UpdWaitActor ActorId
aid (Int -> Watchfulness
WWait Int
0) Watchfulness
WWatch
WWait Int
n -> case Maybe Bool
mwait of
Just Bool
True ->
if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
500 then
if Bool -> Bool
not Bool
uneasy
Bool -> Bool -> Bool
&& Skills -> Bool
canSleep Skills
actorMaxSk
then do
nAll <- GroupName ItemKind -> ActorId -> m Int
forall (m :: * -> *).
MonadServerAtomic m =>
GroupName ItemKind -> ActorId -> m Int
removeConditionSingle GroupName ItemKind
IK.S_BRACED ActorId
aid
let !_A = Bool -> () -> ()
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Int
nAll Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0) ()
addSleep aid
else
UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId -> Watchfulness -> Watchfulness -> UpdAtomic
UpdWaitActor ActorId
aid (Int -> Watchfulness
WWait Int
n) (Int -> Watchfulness
WWait Int
1)
else
UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId -> Watchfulness -> Watchfulness -> UpdAtomic
UpdWaitActor ActorId
aid (Int -> Watchfulness
WWait Int
n) (Int -> Watchfulness
WWait (Int -> Watchfulness) -> Int -> Watchfulness
forall a b. (a -> b) -> a -> b
$ Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
Maybe Bool
_ -> do
nAll <- GroupName ItemKind -> ActorId -> m Int
forall (m :: * -> *).
MonadServerAtomic m =>
GroupName ItemKind -> ActorId -> m Int
removeConditionSingle GroupName ItemKind
IK.S_BRACED ActorId
aid
let !_A = Bool -> () -> ()
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Int
nAll Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 Bool -> Int -> Bool
forall v. Show v => Bool -> v -> Bool
`blame` Int
nAll) ()
execUpdAtomic $ UpdWaitActor aid (WWait n) WWatch
Watchfulness
WSleep ->
if Maybe Bool
mwait Maybe Bool -> Maybe Bool -> Bool
forall a. Eq a => a -> a -> Bool
/= Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
False
Bool -> Bool -> Bool
&& (Maybe Bool -> Bool
forall a. Maybe a -> Bool
isNothing Maybe Bool
mwait
Bool -> Bool -> Bool
|| Bool
uneasy
Bool -> Bool -> Bool
|| Bool -> Bool
not (ResDelta -> Bool
deltaBenign (ResDelta -> Bool) -> ResDelta -> Bool
forall a b. (a -> b) -> a -> b
$ Actor -> ResDelta
bhpDelta Actor
b))
then UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId -> Watchfulness -> Watchfulness -> UpdAtomic
UpdWaitActor ActorId
aid Watchfulness
WSleep Watchfulness
WWake
else UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId -> Int64 -> UpdAtomic
UpdRefillHP ActorId
aid Int64
10000
Watchfulness
WWake -> Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Maybe Bool
mwait Maybe Bool -> Maybe Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
False) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
ActorId -> m ()
forall (m :: * -> *). MonadServerAtomic m => ActorId -> m ()
removeSleepSingle ActorId
aid
affectStash :: MonadServerAtomic m => Actor -> m ()
affectStash :: forall (m :: * -> *). MonadServerAtomic m => Actor -> m ()
affectStash Actor
b = do
let locateStash :: (FactionId, Faction) -> m ()
locateStash (FactionId
fid, Faction
fact) = case Faction -> Maybe (LevelId, Point)
gstash Faction
fact of
Just (LevelId
lidS, Point
posS)
| LevelId
lidS LevelId -> LevelId -> Bool
forall a. Eq a => a -> a -> Bool
== Actor -> LevelId
blid Actor
b Bool -> Bool -> Bool
&& Point
posS Point -> Point -> Bool
forall a. Eq a => a -> a -> Bool
== Actor -> Point
bpos Actor
b Bool -> Bool -> Bool
&& FactionId
fid FactionId -> FactionId -> Bool
forall a. Eq a => a -> a -> Bool
/= Actor -> FactionId
bfid Actor
b ->
UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ Bool -> FactionId -> LevelId -> Point -> UpdAtomic
UpdLoseStashFaction Bool
True FactionId
fid LevelId
lidS Point
posS
Maybe (LevelId, Point)
_ -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
factionD <- (State -> FactionDict) -> m FactionDict
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState State -> FactionDict
sfactionD
mapM_ locateStash $ EM.assocs factionD
handleRequestTimed :: MonadServerAtomic m
=> FactionId -> ActorId -> RequestTimed -> m Bool
handleRequestTimed :: forall (m :: * -> *).
MonadServerAtomic m =>
FactionId -> ActorId -> RequestTimed -> m Bool
handleRequestTimed FactionId
fid ActorId
aid RequestTimed
cmd = do
let mwait :: Maybe Bool
mwait = RequestTimed -> Maybe Bool
checkWaiting RequestTimed
cmd
b <- (State -> Actor) -> m Actor
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> Actor) -> m Actor) -> (State -> Actor) -> m Actor
forall a b. (a -> b) -> a -> b
$ ActorId -> State -> Actor
getActorBody ActorId
aid
unless (mwait == Just True) $ overheadActorTime fid (blid b)
advanceTime aid (if mwait == Just False then 10 else 100) True
handleRequestTimedCases aid cmd
managePerRequest aid
processWatchfulness mwait aid
return $! isNothing mwait
managePerRequest :: MonadServerAtomic m => ActorId -> m ()
managePerRequest :: forall (m :: * -> *). MonadServerAtomic m => ActorId -> m ()
managePerRequest ActorId
aid = do
b <- (State -> Actor) -> m Actor
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> Actor) -> m Actor) -> (State -> Actor) -> m Actor
forall a b. (a -> b) -> a -> b
$ ActorId -> State -> Actor
getActorBody ActorId
aid
affectStash b
let clearMark = Int64
0
unless (bcalmDelta b == ResDelta (0, 0) (0, 0)) $
execUpdAtomic $ UpdRefillCalm aid clearMark
unless (bhpDelta b == ResDelta (0, 0) (0, 0)) $
execUpdAtomic $ UpdRefillHP aid clearMark
handleRequestTimedCases :: MonadServerAtomic m
=> ActorId -> RequestTimed -> m ()
handleRequestTimedCases :: forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> RequestTimed -> m ()
handleRequestTimedCases ActorId
aid RequestTimed
cmd = case RequestTimed
cmd of
ReqMove Vector
target -> ActorId -> Vector -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> Vector -> m ()
reqMove ActorId
aid Vector
target
ReqMelee ActorId
target ItemId
iid CStore
cstore -> ActorId -> ActorId -> ItemId -> CStore -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> ActorId -> ItemId -> CStore -> m ()
reqMelee ActorId
aid ActorId
target ItemId
iid CStore
cstore
ReqDisplace ActorId
target -> ActorId -> ActorId -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> ActorId -> m ()
reqDisplace ActorId
aid ActorId
target
ReqAlter Point
tpos -> ActorId -> Point -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> Point -> m ()
reqAlter ActorId
aid Point
tpos
RequestTimed
ReqWait -> ActorId -> m ()
forall (m :: * -> *). MonadServerAtomic m => ActorId -> m ()
reqWait ActorId
aid
RequestTimed
ReqWait10 -> ActorId -> m ()
forall (m :: * -> *). MonadServerAtomic m => ActorId -> m ()
reqWait10 ActorId
aid
RequestTimed
ReqYell -> ActorId -> m ()
forall (m :: * -> *). MonadServerAtomic m => ActorId -> m ()
reqYell ActorId
aid
ReqMoveItems [(ItemId, Int, CStore, CStore)]
l -> ActorId -> [(ItemId, Int, CStore, CStore)] -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> [(ItemId, Int, CStore, CStore)] -> m ()
reqMoveItems ActorId
aid [(ItemId, Int, CStore, CStore)]
l
ReqProject Point
p Int
eps ItemId
iid CStore
cstore -> ActorId -> Point -> Int -> ItemId -> CStore -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> Point -> Int -> ItemId -> CStore -> m ()
reqProject ActorId
aid Point
p Int
eps ItemId
iid CStore
cstore
ReqApply ItemId
iid CStore
cstore -> ActorId -> ItemId -> CStore -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> ItemId -> CStore -> m ()
reqApply ActorId
aid ItemId
iid CStore
cstore
switchLeader :: MonadServerAtomic m => FactionId -> ActorId -> m ()
{-# INLINE switchLeader #-}
switchLeader :: forall (m :: * -> *).
MonadServerAtomic m =>
FactionId -> ActorId -> m ()
switchLeader FactionId
fid ActorId
aidNew = do
fact <- (State -> Faction) -> m Faction
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> Faction) -> m Faction)
-> (State -> Faction) -> m Faction
forall a b. (a -> b) -> a -> b
$ (FactionDict -> FactionId -> Faction
forall k a. Enum k => EnumMap k a -> k -> a
EM.! FactionId
fid) (FactionDict -> Faction)
-> (State -> FactionDict) -> State -> Faction
forall b c a. (b -> c) -> (a -> b) -> a -> c
. State -> FactionDict
sfactionD
bPre <- getsState $ getActorBody aidNew
let mleader = Faction -> Maybe ActorId
gleader Faction
fact
!_A1 = Bool -> () -> ()
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (ActorId -> Maybe ActorId
forall a. a -> Maybe a
Just ActorId
aidNew Maybe ActorId -> Maybe ActorId -> Bool
forall a. Eq a => a -> a -> Bool
/= Maybe ActorId
mleader
Bool -> Bool -> Bool
&& Bool -> Bool
not (Actor -> Bool
bproj Actor
bPre)
Bool -> (ActorId, Actor, FactionId, Faction) -> Bool
forall v. Show v => Bool -> v -> Bool
`blame` (ActorId
aidNew, Actor
bPre, FactionId
fid, Faction
fact)) ()
!_A2 = Bool -> () -> ()
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Actor -> FactionId
bfid Actor
bPre FactionId -> FactionId -> Bool
forall a. Eq a => a -> a -> Bool
== FactionId
fid
Bool -> (String, (ActorId, Actor, FactionId, Faction)) -> Bool
forall v. Show v => Bool -> v -> Bool
`blame` String
"client tries to move other faction actors"
String
-> (ActorId, Actor, FactionId, Faction)
-> (String, (ActorId, Actor, FactionId, Faction))
forall v. String -> v -> (String, v)
`swith` (ActorId
aidNew, Actor
bPre, FactionId
fid, Faction
fact)) ()
let banned = Faction -> Bool
bannedPointmanSwitchBetweenLevels Faction
fact
arena <- case mleader of
Maybe ActorId
Nothing -> LevelId -> m LevelId
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (LevelId -> m LevelId) -> LevelId -> m LevelId
forall a b. (a -> b) -> a -> b
$! Actor -> LevelId
blid Actor
bPre
Just ActorId
leader -> do
b <- (State -> Actor) -> m Actor
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> Actor) -> m Actor) -> (State -> Actor) -> m Actor
forall a b. (a -> b) -> a -> b
$ ActorId -> State -> Actor
getActorBody ActorId
leader
return $! blid b
if blid bPre /= arena && banned
then execFailure aidNew ReqWait NoChangeDunLeader
else do
execUpdAtomic $ UpdLeadFaction fid mleader (Just aidNew)
case mleader of
Just ActorId
aidOld | ActorId
aidOld ActorId -> ActorId -> Bool
forall a. Eq a => a -> a -> Bool
/= ActorId
aidNew -> ActorId -> ActorId -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> ActorId -> m ()
swapTime ActorId
aidOld ActorId
aidNew
Maybe ActorId
_ -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
affectSmell :: MonadServerAtomic m => ActorId -> m ()
affectSmell :: forall (m :: * -> *). MonadServerAtomic m => ActorId -> m ()
affectSmell ActorId
aid = do
COps{coTileSpeedup} <- (State -> COps) -> m COps
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState State -> COps
scops
b <- getsState $ getActorBody aid
lvl <- getLevel $ blid b
let aquatic = TileSpeedup -> ContentId TileKind -> Bool
Tile.isAquatic TileSpeedup
coTileSpeedup (ContentId TileKind -> Bool) -> ContentId TileKind -> Bool
forall a b. (a -> b) -> a -> b
$ Level
lvl Level -> Point -> ContentId TileKind
`at` Actor -> Point
bpos Actor
b
unless (bproj b || aquatic) $ do
actorMaxSk <- getsState $ getActorMaxSkills aid
let smellRadius = Skill -> Skills -> Int
Ability.getSk Skill
Ability.SkSmell Skills
actorMaxSk
hasOdor = Skill -> Skills -> Int
Ability.getSk Skill
Ability.SkOdor Skills
actorMaxSk Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
when (hasOdor || smellRadius > 0) $ do
localTime <- getsState $ getLocalTime $ blid b
let oldS = Time -> Maybe Time -> Time
forall a. a -> Maybe a -> a
fromMaybe Time
timeZero (Maybe Time -> Time) -> Maybe Time -> Time
forall a b. (a -> b) -> a -> b
$ Point -> EnumMap Point Time -> Maybe Time
forall k a. Enum k => k -> EnumMap k a -> Maybe a
EM.lookup (Actor -> Point
bpos Actor
b) (EnumMap Point Time -> Maybe Time)
-> (Level -> EnumMap Point Time) -> Level -> Maybe Time
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Level -> EnumMap Point Time
lsmell (Level -> Maybe Time) -> Level -> Maybe Time
forall a b. (a -> b) -> a -> b
$ Level
lvl
newTime = Time -> Delta Time -> Time
timeShift Time
localTime Delta Time
smellTimeout
newS = if Int
smellRadius Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
then Time
timeZero
else Time
newTime
when (oldS /= newS) $
execUpdAtomic $ UpdAlterSmell (blid b) (bpos b) oldS newS
reqMove :: MonadServerAtomic m => ActorId -> Vector -> m ()
reqMove :: forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> Vector -> m ()
reqMove = Bool -> Bool -> ActorId -> Vector -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
Bool -> Bool -> ActorId -> Vector -> m ()
reqMoveGeneric Bool
True Bool
True
reqMoveGeneric :: MonadServerAtomic m
=> Bool -> Bool -> ActorId -> Vector -> m ()
reqMoveGeneric :: forall (m :: * -> *).
MonadServerAtomic m =>
Bool -> Bool -> ActorId -> Vector -> m ()
reqMoveGeneric Bool
voluntary Bool
mayAttack ActorId
source Vector
dir = do
COps{coTileSpeedup} <- (State -> COps) -> m COps
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState State -> COps
scops
actorSk <- currentSkillsServer source
sb <- getsState $ getActorBody source
let abInSkill Skill
sk = Maybe ([Vector], Speed) -> Bool
forall a. Maybe a -> Bool
isJust (Actor -> Maybe ([Vector], Speed)
btrajectory Actor
sb)
Bool -> Bool -> Bool
|| Skill -> Skills -> Int
Ability.getSk Skill
sk Skills
actorSk Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
lid = Actor -> LevelId
blid Actor
sb
lvl <- getLevel lid
let spos = Actor -> Point
bpos Actor
sb
tpos = Point
spos Point -> Vector -> Point
`shift` Vector
dir
collides <- getsState $ \State
s Actor
tb ->
let sitemKind :: ItemKind
sitemKind = ItemId -> State -> ItemKind
getIidKindServer (Actor -> ItemId
btrunk Actor
sb) State
s
titemKind :: ItemKind
titemKind = ItemId -> State -> ItemKind
getIidKindServer (Actor -> ItemId
btrunk Actor
tb) State
s
sar :: AspectRecord
sar = State -> DiscoveryAspect
sdiscoAspect State
s DiscoveryAspect -> ItemId -> AspectRecord
forall k a. Enum k => EnumMap k a -> k -> a
EM.! Actor -> ItemId
btrunk Actor
sb
tar :: AspectRecord
tar = State -> DiscoveryAspect
sdiscoAspect State
s DiscoveryAspect -> ItemId -> AspectRecord
forall k a. Enum k => EnumMap k a -> k -> a
EM.! Actor -> ItemId
btrunk Actor
tb
bursting :: AspectRecord -> Bool
bursting AspectRecord
arItem =
Flag -> AspectRecord -> Bool
IA.checkFlag Flag
Ability.Fragile AspectRecord
arItem
Bool -> Bool -> Bool
&& Flag -> AspectRecord -> Bool
IA.checkFlag Flag
Ability.Lobable AspectRecord
arItem
sbursting :: Bool
sbursting = AspectRecord -> Bool
bursting AspectRecord
sar
tbursting :: Bool
tbursting = AspectRecord -> Bool
bursting AspectRecord
tar
sdamaging :: Bool
sdamaging = ItemKind -> Bool
IK.isDamagingKind ItemKind
sitemKind
tdamaging :: Bool
tdamaging = ItemKind -> Bool
IK.isDamagingKind ItemKind
titemKind
sameBlast :: Bool
sameBlast = Flag -> AspectRecord -> Bool
IA.checkFlag Flag
Ability.Blast AspectRecord
sar
Bool -> Bool -> Bool
&& ItemId -> State -> ContentId ItemKind
getIidKindIdServer (Actor -> ItemId
btrunk Actor
sb) State
s
ContentId ItemKind -> ContentId ItemKind -> Bool
forall a. Eq a => a -> a -> Bool
== ItemId -> State -> ContentId ItemKind
getIidKindIdServer (Actor -> ItemId
btrunk Actor
tb) State
s
in Bool -> Bool
not Bool
sameBlast
Bool -> Bool -> Bool
&& (Bool
sbursting Bool -> Bool -> Bool
&& (Bool
tdamaging Bool -> Bool -> Bool
|| Bool
tbursting)
Bool -> Bool -> Bool
|| (Bool
tbursting Bool -> Bool -> Bool
&& (Bool
sdamaging Bool -> Bool -> Bool
|| Bool
sbursting)))
tgt <- getsState $ posToAidAssocs tpos lid
case tgt of
(ActorId
target, Actor
tb) : [(ActorId, Actor)]
_ | Bool
mayAttack Bool -> Bool -> Bool
&& (Bool -> Bool
not (Actor -> Bool
bproj Actor
sb)
Bool -> Bool -> Bool
|| Bool -> Bool
not (Actor -> Bool
bproj Actor
tb)
Bool -> Bool -> Bool
|| Actor -> Bool
collides Actor
tb) -> do
mweapon <- ActorId -> ActorId -> m (Maybe (ItemId, CStore))
forall (m :: * -> *).
MonadServer m =>
ActorId -> ActorId -> m (Maybe (ItemId, CStore))
pickWeaponServer ActorId
source ActorId
target
case mweapon of
Just (ItemId
wp, CStore
cstore) | Skill -> Bool
abInSkill Skill
Ability.SkMelee ->
Bool -> ActorId -> ActorId -> ItemId -> CStore -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
Bool -> ActorId -> ActorId -> ItemId -> CStore -> m ()
reqMeleeChecked Bool
voluntary ActorId
source ActorId
target ItemId
wp CStore
cstore
Maybe (ItemId, CStore)
_ -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
when (bproj sb) $ do
b2 <- getsState $ getActorBody source
unless (actorDying b2) $ reqMoveGeneric voluntary False source dir
[(ActorId, Actor)]
_ ->
if TileSpeedup -> ContentId TileKind -> Bool
Tile.isWalkable TileSpeedup
coTileSpeedup (ContentId TileKind -> Bool) -> ContentId TileKind -> Bool
forall a b. (a -> b) -> a -> b
$ Level
lvl Level -> Point -> ContentId TileKind
`at` Point
tpos then
if Skill -> Bool
abInSkill Skill
Ability.SkMove then do
UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId -> Point -> Point -> UpdAtomic
UpdMoveActor ActorId
source Point
spos Point
tpos
ActorId -> m ()
forall (m :: * -> *). MonadServerAtomic m => ActorId -> m ()
affectSmell ActorId
source
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Actor -> Bool
bproj Actor
sb) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
m (Maybe ReqFailure) -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m (Maybe ReqFailure) -> m ()) -> m (Maybe ReqFailure) -> m ()
forall a b. (a -> b) -> a -> b
$ Bool
-> EffToUse -> Bool -> ActorId -> Point -> m (Maybe ReqFailure)
forall (m :: * -> *).
MonadServerAtomic m =>
Bool
-> EffToUse -> Bool -> ActorId -> Point -> m (Maybe ReqFailure)
reqAlterFail Bool
True EffToUse
EffBare Bool
voluntary ActorId
source Point
tpos
else ActorId -> RequestTimed -> ReqFailure -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> RequestTimed -> ReqFailure -> m ()
execFailure ActorId
source (Vector -> RequestTimed
ReqMove Vector
dir) ReqFailure
MoveUnskilled
else do
mfail <- Bool
-> EffToUse -> Bool -> ActorId -> Point -> m (Maybe ReqFailure)
forall (m :: * -> *).
MonadServerAtomic m =>
Bool
-> EffToUse -> Bool -> ActorId -> Point -> m (Maybe ReqFailure)
reqAlterFail Bool
True EffToUse
EffBare Bool
voluntary ActorId
source Point
tpos
when voluntary $ do
let req = Vector -> RequestTimed
ReqMove Vector
dir
maybe (return ()) (execFailure source req) mfail
reqMelee :: MonadServerAtomic m
=> ActorId -> ActorId -> ItemId -> CStore -> m ()
reqMelee :: forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> ActorId -> ItemId -> CStore -> m ()
reqMelee ActorId
source ActorId
target ItemId
iid CStore
cstore = do
actorSk <- ActorId -> m Skills
forall (m :: * -> *). MonadServer m => ActorId -> m Skills
currentSkillsServer ActorId
source
if Ability.getSk Ability.SkMelee actorSk > 0 then
reqMeleeChecked True source target iid cstore
else execFailure source (ReqMelee target iid cstore) MeleeUnskilled
reqMeleeChecked :: forall m. MonadServerAtomic m
=> Bool -> ActorId -> ActorId -> ItemId -> CStore -> m ()
reqMeleeChecked :: forall (m :: * -> *).
MonadServerAtomic m =>
Bool -> ActorId -> ActorId -> ItemId -> CStore -> m ()
reqMeleeChecked Bool
voluntary ActorId
source ActorId
target ItemId
iid CStore
cstore = do
sb <- (State -> Actor) -> m Actor
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> Actor) -> m Actor) -> (State -> Actor) -> m Actor
forall a b. (a -> b) -> a -> b
$ ActorId -> State -> Actor
getActorBody ActorId
source
tb <- getsState $ getActorBody target
discoAspect <- getsState sdiscoAspect
let req = ActorId -> ItemId -> CStore -> RequestTimed
ReqMelee ActorId
target ItemId
iid CStore
cstore
arWeapon = DiscoveryAspect
discoAspect DiscoveryAspect -> ItemId -> AspectRecord
forall k a. Enum k => EnumMap k a -> k -> a
EM.! ItemId
iid
meleeableEnough = Actor -> Bool
bproj Actor
sb Bool -> Bool -> Bool
|| Flag -> AspectRecord -> Bool
IA.checkFlag Flag
Ability.Meleeable AspectRecord
arWeapon
if source == target then execFailure source req MeleeSelf
else if not (checkAdjacent sb tb) then execFailure source req MeleeDistant
else if not meleeableEnough then execFailure source req MeleeNotWeapon
else do
killer <- if | voluntary -> assert (not (bproj sb)) $ return source
| bproj sb -> getsServer $ EM.findWithDefault source source
. strajPushedBy
| otherwise -> return source
actorSk <- currentSkillsServer source
let arTrunk = DiscoveryAspect
discoAspect DiscoveryAspect -> ItemId -> AspectRecord
forall k a. Enum k => EnumMap k a -> k -> a
EM.! Actor -> ItemId
btrunk Actor
tb
sfid = Actor -> FactionId
bfid Actor
sb
tfid = Actor -> FactionId
bfid Actor
tb
haltTrajectory :: KillHow -> ActorId -> Actor -> m ()
haltTrajectory KillHow
killHow ActorId
aid Actor
b = case Actor -> Maybe ([Vector], Speed)
btrajectory Actor
b of
btra :: Maybe ([Vector], Speed)
btra@(Just ([Vector]
l, Speed
speed)) | Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [Vector] -> Bool
forall a. [a] -> Bool
null [Vector]
l -> do
UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId
-> Maybe ([Vector], Speed) -> Maybe ([Vector], Speed) -> UpdAtomic
UpdTrajectory ActorId
aid Maybe ([Vector], Speed)
btra (Maybe ([Vector], Speed) -> UpdAtomic)
-> Maybe ([Vector], Speed) -> UpdAtomic
forall a b. (a -> b) -> a -> b
$ ([Vector], Speed) -> Maybe ([Vector], Speed)
forall a. a -> Maybe a
Just ([], Speed
speed)
let arTrunkAid :: AspectRecord
arTrunkAid = DiscoveryAspect
discoAspect DiscoveryAspect -> ItemId -> AspectRecord
forall k a. Enum k => EnumMap k a -> k -> a
EM.! Actor -> ItemId
btrunk Actor
b
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Actor -> Bool
bproj Actor
b Bool -> Bool -> Bool
&& Bool -> Bool
not (Flag -> AspectRecord -> Bool
IA.checkFlag Flag
Ability.Blast AspectRecord
arTrunkAid)) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
ActorId -> KillHow -> FactionId -> ItemId -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> KillHow -> FactionId -> ItemId -> m ()
addKillToAnalytics ActorId
killer KillHow
killHow (Actor -> FactionId
bfid Actor
b) (Actor -> ItemId
btrunk Actor
b)
Maybe ([Vector], Speed)
_ -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
if bproj tb
&& EM.size (beqp tb) == 1
&& not (IA.checkFlag Ability.Blast arTrunk)
&& actorWaits sb
&& Ability.getSk Ability.SkMoveItem actorSk > 0
then do
execSfxAtomic $ SfxSteal source target iid
case EM.assocs $ beqp tb of
[(ItemId
iid2, (Int
k, [ItemTimer]
_))] -> do
upds <- Bool -> ItemId -> Int -> Container -> Container -> m [UpdAtomic]
forall (m :: * -> *).
MonadStateRead m =>
Bool -> ItemId -> Int -> Container -> Container -> m [UpdAtomic]
generalMoveItem Bool
True ItemId
iid2 Int
k (ActorId -> CStore -> Container
CActor ActorId
target CStore
CEqp)
(ActorId -> CStore -> Container
CActor ActorId
source CStore
CStash)
mapM_ execUpdAtomic upds
itemFull <- getsState $ itemToFull iid2
discoverIfMinorEffects (CActor source CStash)
iid2 (itemKindId itemFull)
[(ItemId, ItemQuant)]
err -> String -> m ()
forall a. (?callStack::CallStack) => String -> a
error (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ String
"" String -> [(ItemId, ItemQuant)] -> String
forall v. Show v => String -> v -> String
`showFailure` [(ItemId, ItemQuant)]
err
haltTrajectory KillCatch target tb
else do
if bproj sb && bproj tb then do
when (bhp tb > oneM) $
execUpdAtomic $ UpdRefillHP target minusM
when (bhp tb <= oneM) $ do
let killHow | Flag -> AspectRecord -> Bool
IA.checkFlag Flag
Ability.Blast AspectRecord
arWeapon = KillHow
KillKineticBlast
| Bool
otherwise = KillHow
KillKineticRanged
haltTrajectory killHow target tb
unless (IA.checkFlag Ability.Blast arWeapon
&& IA.checkFlag Ability.Blast arTrunk) $
execSfxAtomic $ SfxStrike source target iid
else do
let mayDestroyTarget = Bool -> Bool
not (Actor -> Bool
bproj Actor
tb) Bool -> Bool -> Bool
|| Actor -> Int64
bhp Actor
tb Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
oneM
effApplyFlagsTarget = EffApplyFlags
{ effToUse :: EffToUse
effToUse = EffToUse
EffBare
, effVoluntary :: Bool
effVoluntary = Bool
voluntary
, effUseAllCopies :: Bool
effUseAllCopies = Bool
False
, effKineticPerformed :: Bool
effKineticPerformed = Bool
False
, effActivation :: ActivationFlag
effActivation = if Actor -> Bool
bproj Actor
sb
then ActivationFlag
Ability.ActivationUnderRanged
else ActivationFlag
Ability.ActivationUnderMelee
, effMayDestroy :: Bool
effMayDestroy = Bool
mayDestroyTarget
}
unless (bproj tb) $
autoApply effApplyFlagsTarget killer target tb
$ if bproj sb then Ability.UnderRanged else Ability.UnderMelee
sb2 <- getsState $ getActorBody source
targetMaxSk <- getsState $ getActorMaxSkills target
if | bproj sb2
&& Ability.getSk Ability.SkDeflectRanged targetMaxSk > 0 -> do
cutCalm target
execSfxAtomic $ SfxRecoil source target iid
| Ability.getSk Ability.SkDeflectMelee targetMaxSk > 0 -> do
cutCalm target
execSfxAtomic $ SfxRecoil source target iid
| otherwise -> do
execSfxAtomic $ SfxStrike source target iid
let c = ActorId -> CStore -> Container
CActor ActorId
source CStore
cstore
mayDestroySource = Bool -> Bool
not (Actor -> Bool
bproj Actor
sb2) Bool -> Bool -> Bool
|| Actor -> Int64
bhp Actor
sb2 Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
oneM
let effApplyFlagsSource = EffApplyFlags
{ effToUse :: EffToUse
effToUse = EffToUse
EffBare
, effVoluntary :: Bool
effVoluntary = Bool
voluntary
, effUseAllCopies :: Bool
effUseAllCopies = Bool
False
, effKineticPerformed :: Bool
effKineticPerformed = Bool
False
, effActivation :: ActivationFlag
effActivation = ActivationFlag
Ability.ActivationMeleeable
, effMayDestroy :: Bool
effMayDestroy = Bool
mayDestroySource
}
void $ kineticEffectAndDestroy effApplyFlagsSource killer
source target iid c
sb2 <- getsState $ getActorBody source
case btrajectory sb2 of
Just{} | Bool -> Bool
not Bool
voluntary -> do
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Actor -> Int64
bhp Actor
sb2 Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
oneM) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ do
UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId -> Int64 -> UpdAtomic
UpdRefillHP ActorId
source Int64
minusM
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Actor -> Bool
bproj Actor
sb2) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ do
SfxAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => SfxAtomic -> m ()
execSfxAtomic (SfxAtomic -> m ()) -> SfxAtomic -> m ()
forall a b. (a -> b) -> a -> b
$
FactionId -> SfxMsg -> SfxAtomic
SfxMsgFid (Actor -> FactionId
bfid Actor
sb2) (SfxMsg -> SfxAtomic) -> SfxMsg -> SfxAtomic
forall a b. (a -> b) -> a -> b
$ ActorId -> ActorId -> SfxMsg
SfxCollideActor ActorId
source ActorId
target
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Actor -> Bool
bproj Actor
tb) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
SfxAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => SfxAtomic -> m ()
execSfxAtomic (SfxAtomic -> m ()) -> SfxAtomic -> m ()
forall a b. (a -> b) -> a -> b
$
FactionId -> SfxMsg -> SfxAtomic
SfxMsgFid (Actor -> FactionId
bfid Actor
tb) (SfxMsg -> SfxAtomic) -> SfxMsg -> SfxAtomic
forall a b. (a -> b) -> a -> b
$ ActorId -> ActorId -> SfxMsg
SfxCollideActor ActorId
source ActorId
target
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not (Actor -> Bool
bproj Actor
sb2) Bool -> Bool -> Bool
|| Actor -> Int64
bhp Actor
sb2 Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
oneM) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
KillHow -> ActorId -> Actor -> m ()
haltTrajectory KillHow
KillActorLaunch ActorId
source Actor
sb2
Maybe ([Vector], Speed)
_ -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
sfact <- getsState $ (EM.! sfid) . sfactionD
let friendlyFire = Actor -> Bool
bproj Actor
sb2 Bool -> Bool -> Bool
|| Actor -> Bool
bproj Actor
tb Bool -> Bool -> Bool
|| Bool -> Bool
not Bool
voluntary
fromDipl = Diplomacy -> FactionId -> EnumMap FactionId Diplomacy -> Diplomacy
forall k a. Enum k => a -> k -> EnumMap k a -> a
EM.findWithDefault Diplomacy
Unknown FactionId
tfid (Faction -> EnumMap FactionId Diplomacy
gdipl Faction
sfact)
unless (friendlyFire
|| isFoe sfid sfact tfid
|| isFriend sfid sfact tfid) $
execUpdAtomic $ UpdDiplFaction sfid tfid fromDipl War
autoApply :: MonadServerAtomic m
=> EffApplyFlags -> ActorId -> ActorId -> Actor -> Ability.Flag
-> m ()
autoApply :: forall (m :: * -> *).
MonadServerAtomic m =>
EffApplyFlags -> ActorId -> ActorId -> Actor -> Flag -> m ()
autoApply EffApplyFlags
effApplyFlags ActorId
killer ActorId
target Actor
tb Flag
flag = do
let autoApplyIid :: Container -> ItemId -> m ()
autoApplyIid Container
c ItemId
iid = do
itemFull <- (State -> ItemFull) -> m ItemFull
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> ItemFull) -> m ItemFull)
-> (State -> ItemFull) -> m ItemFull
forall a b. (a -> b) -> a -> b
$ ItemId -> State -> ItemFull
itemToFull ItemId
iid
let arItem = ItemFull -> AspectRecord
aspectRecordFull ItemFull
itemFull
when (IA.checkFlag flag arItem) $
void $ effectAndDestroyAndAddKill effApplyFlags killer target target
iid c itemFull
(ItemId -> m ()) -> [ItemId] -> m ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
(a -> m ()) -> t a -> m ()
mapM_ (Container -> ItemId -> m ()
autoApplyIid (Container -> ItemId -> m ()) -> Container -> ItemId -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId -> CStore -> Container
CActor ActorId
target CStore
CEqp) ([ItemId] -> m ()) -> [ItemId] -> m ()
forall a b. (a -> b) -> a -> b
$ EnumMap ItemId ItemQuant -> [ItemId]
forall k a. Enum k => EnumMap k a -> [k]
EM.keys (EnumMap ItemId ItemQuant -> [ItemId])
-> EnumMap ItemId ItemQuant -> [ItemId]
forall a b. (a -> b) -> a -> b
$ Actor -> EnumMap ItemId ItemQuant
beqp Actor
tb
(ItemId -> m ()) -> [ItemId] -> m ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
(a -> m ()) -> t a -> m ()
mapM_ (Container -> ItemId -> m ()
autoApplyIid (Container -> ItemId -> m ()) -> Container -> ItemId -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId -> CStore -> Container
CActor ActorId
target CStore
COrgan) ([ItemId] -> m ()) -> [ItemId] -> m ()
forall a b. (a -> b) -> a -> b
$ EnumMap ItemId ItemQuant -> [ItemId]
forall k a. Enum k => EnumMap k a -> [k]
EM.keys (EnumMap ItemId ItemQuant -> [ItemId])
-> EnumMap ItemId ItemQuant -> [ItemId]
forall a b. (a -> b) -> a -> b
$ Actor -> EnumMap ItemId ItemQuant
borgan Actor
tb
reqDisplace :: MonadServerAtomic m => ActorId -> ActorId -> m ()
reqDisplace :: forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> ActorId -> m ()
reqDisplace = Bool -> ActorId -> ActorId -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
Bool -> ActorId -> ActorId -> m ()
reqDisplaceGeneric Bool
True
reqDisplaceGeneric :: MonadServerAtomic m => Bool -> ActorId -> ActorId -> m ()
reqDisplaceGeneric :: forall (m :: * -> *).
MonadServerAtomic m =>
Bool -> ActorId -> ActorId -> m ()
reqDisplaceGeneric Bool
voluntary ActorId
source ActorId
target = do
COps{coTileSpeedup} <- (State -> COps) -> m COps
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState State -> COps
scops
actorSk <- currentSkillsServer source
sb <- getsState $ getActorBody source
let abInSkill Skill
sk = Maybe ([Vector], Speed) -> Bool
forall a. Maybe a -> Bool
isJust (Actor -> Maybe ([Vector], Speed)
btrajectory Actor
sb)
Bool -> Bool -> Bool
|| Skill -> Skills -> Int
Ability.getSk Skill
sk Skills
actorSk Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
tb <- getsState $ getActorBody target
tfact <- getsState $ (EM.! bfid tb) . sfactionD
let spos = Actor -> Point
bpos Actor
sb
tpos = Actor -> Point
bpos Actor
tb
atWar = FactionId -> Faction -> FactionId -> Bool
isFoe (Actor -> FactionId
bfid Actor
tb) Faction
tfact (Actor -> FactionId
bfid Actor
sb)
req = ActorId -> RequestTimed
ReqDisplace ActorId
target
actorMaxSk <- getsState $ getActorMaxSkills target
dEnemy <- getsState $ dispEnemy source target actorMaxSk
if | not (abInSkill Ability.SkDisplace) ->
execFailure source req DisplaceUnskilled
| not (checkAdjacent sb tb) -> execFailure source req DisplaceDistant
| atWar && not dEnemy -> do
mweapon <- pickWeaponServer source target
case mweapon of
Just (ItemId
wp, CStore
cstore) | Skill -> Bool
abInSkill Skill
Ability.SkMelee ->
Bool -> ActorId -> ActorId -> ItemId -> CStore -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
Bool -> ActorId -> ActorId -> ItemId -> CStore -> m ()
reqMeleeChecked Bool
voluntary ActorId
source ActorId
target ItemId
wp CStore
cstore
Maybe (ItemId, CStore)
_ -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
| otherwise -> do
let lid = Actor -> LevelId
blid Actor
sb
lvl <- getLevel lid
if Tile.isWalkable coTileSpeedup $ lvl `at` tpos then
case posToAidsLvl tpos lvl of
[] -> String -> m ()
forall a. (?callStack::CallStack) => String -> a
error (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ String
"" String -> (ActorId, Actor, ActorId, Actor) -> String
forall v. Show v => String -> v -> String
`showFailure` (ActorId
source, Actor
sb, ActorId
target, Actor
tb)
[ActorId
_] -> do
UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId -> ActorId -> UpdAtomic
UpdDisplaceActor ActorId
source ActorId
target
ActorId -> m ()
forall (m :: * -> *). MonadServerAtomic m => ActorId -> m ()
affectSmell ActorId
source
ActorId -> m ()
forall (m :: * -> *). MonadServerAtomic m => ActorId -> m ()
affectSmell ActorId
target
m (Maybe ReqFailure) -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m (Maybe ReqFailure) -> m ()) -> m (Maybe ReqFailure) -> m ()
forall a b. (a -> b) -> a -> b
$ Bool
-> EffToUse -> Bool -> ActorId -> Point -> m (Maybe ReqFailure)
forall (m :: * -> *).
MonadServerAtomic m =>
Bool
-> EffToUse -> Bool -> ActorId -> Point -> m (Maybe ReqFailure)
reqAlterFail Bool
True EffToUse
EffBare Bool
False ActorId
source Point
tpos
m (Maybe ReqFailure) -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m (Maybe ReqFailure) -> m ()) -> m (Maybe ReqFailure) -> m ()
forall a b. (a -> b) -> a -> b
$ Bool
-> EffToUse -> Bool -> ActorId -> Point -> m (Maybe ReqFailure)
forall (m :: * -> *).
MonadServerAtomic m =>
Bool
-> EffToUse -> Bool -> ActorId -> Point -> m (Maybe ReqFailure)
reqAlterFail Bool
True EffToUse
EffBare Bool
False ActorId
target Point
spos
[ActorId]
_ -> ActorId -> RequestTimed -> ReqFailure -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> RequestTimed -> ReqFailure -> m ()
execFailure ActorId
source RequestTimed
req ReqFailure
DisplaceMultiple
else
execFailure source req DisplaceAccess
reqAlter :: MonadServerAtomic m => ActorId -> Point -> m ()
reqAlter :: forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> Point -> m ()
reqAlter ActorId
source Point
tpos = do
COps{coTileSpeedup} <- (State -> COps) -> m COps
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState State -> COps
scops
sb <- getsState $ getActorBody source
lvl <- getLevel $ blid sb
let effToUse = if TileSpeedup -> ContentId TileKind -> Bool
Tile.isWalkable TileSpeedup
coTileSpeedup (Level
lvl Level -> Point -> ContentId TileKind
`at` Point
tpos)
then EffToUse
EffOnCombine
else EffToUse
EffBareAndOnCombine
mfail <- reqAlterFail False effToUse True source tpos
let req = Point -> RequestTimed
ReqAlter Point
tpos
maybe (return ()) (execFailure source req) mfail
reqAlterFail :: forall m. MonadServerAtomic m
=> Bool -> EffToUse -> Bool -> ActorId -> Point
-> m (Maybe ReqFailure)
reqAlterFail :: forall (m :: * -> *).
MonadServerAtomic m =>
Bool
-> EffToUse -> Bool -> ActorId -> Point -> m (Maybe ReqFailure)
reqAlterFail Bool
bumping EffToUse
effToUse Bool
voluntary ActorId
source Point
tpos = do
cops@COps{cotile, coTileSpeedup, corule} <- (State -> COps) -> m COps
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState State -> COps
scops
sb <- getsState $ getActorBody source
actorMaxSk <- getsState $ getActorMaxSkills source
let calmE = Actor -> Skills -> Bool
calmEnough Actor
sb Skills
actorMaxSk
lid = Actor -> LevelId
blid Actor
sb
sClient <- getsServer $ (EM.! bfid sb) . sclientStates
itemToF <- getsState $ flip itemToFull
actorSk <- currentSkillsServer source
localTime <- getsState $ getLocalTime lid
embeds <- getsState $ getEmbedBag lid tpos
lvl <- getLevel lid
getKind <- getsState $ flip getIidKindServer
let serverTile = Level
lvl Level -> Point -> ContentId TileKind
`at` Point
tpos
lvlClient = (EnumMap LevelId Level -> LevelId -> Level
forall k a. Enum k => EnumMap k a -> k -> a
EM.! LevelId
lid) (EnumMap LevelId Level -> Level)
-> (State -> EnumMap LevelId Level) -> State -> Level
forall b c a. (b -> c) -> (a -> b) -> a -> c
. State -> EnumMap LevelId Level
sdungeon (State -> Level) -> State -> Level
forall a b. (a -> b) -> a -> b
$ State
sClient
clientTile = Level
lvlClient Level -> Point -> ContentId TileKind
`at` Point
tpos
hiddenTile = ContentData TileKind
-> ContentId TileKind -> Maybe (ContentId TileKind)
Tile.hideAs ContentData TileKind
cotile ContentId TileKind
serverTile
alterSkill = Skill -> Skills -> Int
Ability.getSk Skill
Ability.SkAlter Skills
actorSk
tileMinSkill = TileSpeedup -> ContentId TileKind -> Int
Tile.alterMinSkill TileSpeedup
coTileSpeedup ContentId TileKind
serverTile
revealEmbeds = Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (EnumMap ItemId ItemQuant -> Bool
forall k a. EnumMap k a -> Bool
EM.null EnumMap ItemId ItemQuant
embeds) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ Bool -> Container -> EnumMap ItemId ItemQuant -> UpdAtomic
UpdSpotItemBag Bool
True (LevelId -> Point -> Container
CEmbed LevelId
lid Point
tpos) EnumMap ItemId ItemQuant
embeds
embedKindList =
((ItemId, ItemQuant) -> (ItemKind, (ItemId, ItemQuant)))
-> [(ItemId, ItemQuant)] -> [(ItemKind, (ItemId, ItemQuant))]
forall a b. (a -> b) -> [a] -> [b]
map (\(ItemId
iid, ItemQuant
kit) -> (ItemId -> ItemKind
getKind ItemId
iid, (ItemId
iid, ItemQuant
kit))) (EnumMap ItemId ItemQuant -> [(ItemId, ItemQuant)]
forall k a. Enum k => EnumMap k a -> [(k, a)]
EM.assocs EnumMap ItemId ItemQuant
embeds)
sbItemKind = ItemId -> ItemKind
getKind (ItemId -> ItemKind) -> ItemId -> ItemKind
forall a b. (a -> b) -> a -> b
$ Actor -> ItemId
btrunk Actor
sb
projNoDamage = Actor -> Bool
bproj Actor
sb Bool -> Bool -> Bool
&& Bool -> Bool
not (ItemKind -> Bool
IK.isDamagingKind ItemKind
sbItemKind)
tryApplyEmbed (ItemId
iid, ItemQuant
kit) = do
let itemFull :: ItemFull
itemFull = ItemId -> ItemFull
itemToF ItemId
iid
legal :: Either ReqFailure Bool
legal = RuleContent
-> Time
-> Int
-> Bool
-> Maybe CStore
-> ItemFull
-> ItemQuant
-> Either ReqFailure Bool
permittedApply RuleContent
corule Time
localTime Int
forall a. Bounded a => a
maxBound Bool
calmE Maybe CStore
forall a. Maybe a
Nothing
ItemFull
itemFull ItemQuant
kit
case Either ReqFailure Bool
legal of
Left ReqFailure
ApplyNoEffects -> UseResult -> m UseResult
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return UseResult
UseDud
Left ReqFailure
reqFail -> do
SfxAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => SfxAtomic -> m ()
execSfxAtomic (SfxAtomic -> m ()) -> SfxAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ FactionId -> SfxMsg -> SfxAtomic
SfxMsgFid (Actor -> FactionId
bfid Actor
sb)
(SfxMsg -> SfxAtomic) -> SfxMsg -> SfxAtomic
forall a b. (a -> b) -> a -> b
$ ItemId -> LevelId -> ReqFailure -> SfxMsg
SfxExpectedEmbed ItemId
iid LevelId
lid ReqFailure
reqFail
UseResult -> m UseResult
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return UseResult
UseDud
Either ReqFailure Bool
_ -> EffToUse
-> Bool -> ActorId -> LevelId -> Point -> ItemId -> m UseResult
forall (m :: * -> *).
MonadServerAtomic m =>
EffToUse
-> Bool -> ActorId -> LevelId -> Point -> ItemId -> m UseResult
itemEffectEmbedded EffToUse
effToUse Bool
voluntary ActorId
source LevelId
lid Point
tpos ItemId
iid
underFeet = Point
tpos Point -> Point -> Bool
forall a. Eq a => a -> a -> Bool
== Actor -> Point
bpos Actor
sb
blockedByItem = Point -> EnumMap Point (EnumMap ItemId ItemQuant) -> Bool
forall k a. Enum k => k -> EnumMap k a -> Bool
EM.member Point
tpos (Level -> EnumMap Point (EnumMap ItemId ItemQuant)
lfloor Level
lvl)
if chessDist tpos (bpos sb) > 1
then return $ Just AlterDistant
else if Just clientTile == hiddenTile then
if bproj sb || not underFeet && alterSkill <= 1
then return $ Just AlterUnskilled
else do
execUpdAtomic $ UpdSearchTile source tpos serverTile
revealEmbeds
case EM.lookup tpos $ lentry lvl of
Maybe PlaceEntry
Nothing -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Just PlaceEntry
entry -> UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ LevelId -> [(Point, PlaceEntry)] -> UpdAtomic
UpdSpotEntry LevelId
lid [(Point
tpos, PlaceEntry
entry)]
unless (Tile.isModifiable coTileSpeedup serverTile || projNoDamage) $
mapM_ (void <$> tryApplyEmbed)
(sortEmbeds cops serverTile embedKindList)
return Nothing
else
if not (bproj sb || underFeet)
&& alterSkill < tileMinSkill
then return $ Just AlterUnskilled
else do
groundBag <- getsState $ getBodyStoreBag sb CGround
eqpBag <- getsState $ getBodyStoreBag sb CEqp
kitAssG <- getsState $ kitAssocs source [CGround]
kitAssE <- getsState $ kitAssocs source [CEqp]
let kitAss = [(ItemId, ItemFullKit)]
-> [(ItemId, ItemFullKit)]
-> [((CStore, Bool), (ItemId, ItemFullKit))]
listToolsToConsume [(ItemId, ItemFullKit)]
kitAssG [(ItemId, ItemFullKit)]
kitAssE
announceTileChange =
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Bool
underFeet Bool -> Bool -> Bool
|| EnumMap ItemId ItemQuant -> Bool
forall k a. EnumMap k a -> Bool
EM.null EnumMap ItemId ItemQuant
embeds) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
SfxAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => SfxAtomic -> m ()
execSfxAtomic (SfxAtomic -> m ()) -> SfxAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId -> LevelId -> Point -> ContentId TileKind -> SfxAtomic
SfxTrigger ActorId
source LevelId
lid Point
tpos ContentId TileKind
serverTile
changeTo GroupName TileKind
tgroup = do
let nightCond :: TileKind -> Bool
nightCond TileKind
kt = Bool -> Bool
not (Feature -> TileKind -> Bool
Tile.kindHasFeature Feature
TK.Walkable TileKind
kt
Bool -> Bool -> Bool
&& Feature -> TileKind -> Bool
Tile.kindHasFeature Feature
TK.Clear TileKind
kt)
Bool -> Bool -> Bool
|| (if Level -> Bool
lnight Level
lvl then Bool -> Bool
forall a. a -> a
id else Bool -> Bool
not)
(Feature -> TileKind -> Bool
Tile.kindHasFeature Feature
TK.Dark TileKind
kt)
mtoTile <- Rnd (Maybe (ContentId TileKind)) -> m (Maybe (ContentId TileKind))
forall (m :: * -> *) a. MonadServer m => Rnd a -> m a
rndToAction (Rnd (Maybe (ContentId TileKind))
-> m (Maybe (ContentId TileKind)))
-> Rnd (Maybe (ContentId TileKind))
-> m (Maybe (ContentId TileKind))
forall a b. (a -> b) -> a -> b
$ ContentData TileKind
-> GroupName TileKind
-> (TileKind -> Bool)
-> Rnd (Maybe (ContentId TileKind))
forall a.
Show a =>
ContentData a
-> GroupName a -> (a -> Bool) -> Rnd (Maybe (ContentId a))
opick ContentData TileKind
cotile GroupName TileKind
tgroup TileKind -> Bool
nightCond
toTile <- maybe (rndToAction
$ fromMaybe (error $ "" `showFailure` tgroup)
<$> opick cotile tgroup (const True))
return
mtoTile
embeds2 <- getsState $ getEmbedBag lid tpos
let newHasEmbeds = TileSpeedup -> ContentId TileKind -> Bool
Tile.isEmbed TileSpeedup
coTileSpeedup ContentId TileKind
toTile
when (serverTile /= toTile
|| EM.null embeds2 && newHasEmbeds) $ do
when (serverTile /= toTile) $
execUpdAtomic $ UpdAlterTile lid tpos serverTile toTile
case hiddenTile of
Just ContentId TileKind
tHidden ->
UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ LevelId
-> Point -> ContentId TileKind -> ContentId TileKind -> UpdAtomic
UpdAlterTile LevelId
lid Point
tpos ContentId TileKind
tHidden ContentId TileKind
toTile
Maybe (ContentId TileKind)
Nothing -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
case (Tile.isExplorable coTileSpeedup serverTile,
Tile.isExplorable coTileSpeedup toTile) of
(Bool
False, Bool
True) -> UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ LevelId -> Int -> UpdAtomic
UpdAlterExplorable LevelId
lid Int
1
(Bool
True, Bool
False) -> UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ LevelId -> Int -> UpdAtomic
UpdAlterExplorable LevelId
lid (-Int
1)
(Bool, Bool)
_ -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
unless (EM.null embeds2) $
execUpdAtomic $ UpdLoseItemBag True (CEmbed lid tpos) embeds2
embedItemOnPos lid tpos toTile
tryChangeWith :: ( [(Int, GroupName IK.ItemKind)]
, GroupName TK.TileKind )
-> m Bool
tryChangeWith ([(Int, GroupName ItemKind)]
tools0, GroupName TileKind
tgroup) = do
let grps0 :: [(Bool, Int, GroupName ItemKind)]
grps0 = ((Int, GroupName ItemKind) -> (Bool, Int, GroupName ItemKind))
-> [(Int, GroupName ItemKind)] -> [(Bool, Int, GroupName ItemKind)]
forall a b. (a -> b) -> [a] -> [b]
map (\(Int
x, GroupName ItemKind
y) -> (Bool
False, Int
x, GroupName ItemKind
y)) [(Int, GroupName ItemKind)]
tools0
(EnumMap CStore (EnumMap ItemId ItemQuant)
bagsToLose, [(CStore, (ItemId, ItemFull))]
iidsToApply, [(Bool, Int, GroupName ItemKind)]
grps) =
((EnumMap CStore (EnumMap ItemId ItemQuant),
[(CStore, (ItemId, ItemFull))], [(Bool, Int, GroupName ItemKind)])
-> ((CStore, Bool), (ItemId, ItemFullKit))
-> (EnumMap CStore (EnumMap ItemId ItemQuant),
[(CStore, (ItemId, ItemFull))], [(Bool, Int, GroupName ItemKind)]))
-> (EnumMap CStore (EnumMap ItemId ItemQuant),
[(CStore, (ItemId, ItemFull))], [(Bool, Int, GroupName ItemKind)])
-> [((CStore, Bool), (ItemId, ItemFullKit))]
-> (EnumMap CStore (EnumMap ItemId ItemQuant),
[(CStore, (ItemId, ItemFull))], [(Bool, Int, GroupName ItemKind)])
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (EnumMap CStore (EnumMap ItemId ItemQuant),
[(CStore, (ItemId, ItemFull))], [(Bool, Int, GroupName ItemKind)])
-> ((CStore, Bool), (ItemId, ItemFullKit))
-> (EnumMap CStore (EnumMap ItemId ItemQuant),
[(CStore, (ItemId, ItemFull))], [(Bool, Int, GroupName ItemKind)])
subtractIidfromGrps (EnumMap CStore (EnumMap ItemId ItemQuant)
forall k a. EnumMap k a
EM.empty, [], [(Bool, Int, GroupName ItemKind)]
grps0) [((CStore, Bool), (ItemId, ItemFullKit))]
kitAss
if [(Bool, Int, GroupName ItemKind)] -> Bool
forall a. [a] -> Bool
null [(Bool, Int, GroupName ItemKind)]
grps then do
m ()
announceTileChange
ActorId
-> EnumMap CStore (EnumMap ItemId ItemQuant)
-> [(CStore, (ItemId, ItemFull))]
-> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
ActorId
-> EnumMap CStore (EnumMap ItemId ItemQuant)
-> [(CStore, (ItemId, ItemFull))]
-> m ()
consumeItems ActorId
source EnumMap CStore (EnumMap ItemId ItemQuant)
bagsToLose [(CStore, (ItemId, ItemFull))]
iidsToApply
GroupName TileKind -> m ()
changeTo GroupName TileKind
tgroup
Bool -> m Bool
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
else Bool -> m Bool
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
feats = TileKind -> [Feature]
TK.tfeature (TileKind -> [Feature]) -> TileKind -> [Feature]
forall a b. (a -> b) -> a -> b
$ ContentData TileKind -> ContentId TileKind -> TileKind
forall a. ContentData a -> ContentId a -> a
okind ContentData TileKind
cotile ContentId TileKind
serverTile
tileActions =
(Feature -> Maybe TileAction) -> [Feature] -> [TileAction]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (Bool
-> Bool
-> [(ItemKind, (ItemId, ItemQuant))]
-> Feature
-> Maybe TileAction
parseTileAction
(Actor -> Bool
bproj Actor
sb)
(Bool
underFeet Bool -> Bool -> Bool
|| Bool
blockedByItem)
[(ItemKind, (ItemId, ItemQuant))]
embedKindList)
[Feature]
feats
groupWithFromAction TileAction
action = case TileAction
action of
WithAction [(Int, GroupName ItemKind)]
grps GroupName TileKind
_ | Bool -> Bool
not Bool
bumping -> [(Int, GroupName ItemKind)] -> Maybe [(Int, GroupName ItemKind)]
forall a. a -> Maybe a
Just [(Int, GroupName ItemKind)]
grps
TileAction
_ -> Maybe [(Int, GroupName ItemKind)]
forall a. Maybe a
Nothing
groupsToAlterWith = (TileAction -> Maybe [(Int, GroupName ItemKind)])
-> [TileAction] -> [[(Int, GroupName ItemKind)]]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe TileAction -> Maybe [(Int, GroupName ItemKind)]
groupWithFromAction [TileAction]
tileActions
processTileActions :: Maybe UseResult -> [TileAction] -> m Bool
processTileActions Maybe UseResult
museResult [] =
Bool -> m Bool
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> m Bool) -> Bool -> m Bool
forall a b. (a -> b) -> a -> b
$! Bool -> (UseResult -> Bool) -> Maybe UseResult -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False (UseResult -> UseResult -> Bool
forall a. Eq a => a -> a -> Bool
/= UseResult
UseDud) Maybe UseResult
museResult
processTileActions Maybe UseResult
museResult (TileAction
ta : [TileAction]
rest) = case TileAction
ta of
EmbedAction (ItemId
iid, ItemQuant
kit) ->
if | Actor -> Bool
bproj Actor
sb Bool -> Bool -> Bool
&& Int
tileMinSkill Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 ->
Maybe UseResult -> [TileAction] -> m Bool
processTileActions Maybe UseResult
museResult [TileAction]
rest
| Bool
projNoDamage ->
Maybe UseResult -> [TileAction] -> m Bool
processTileActions (UseResult -> Maybe UseResult
forall a. a -> Maybe a
Just UseResult
UseDud) [TileAction]
rest
| Bool
otherwise -> do
triggered <- (ItemId, ItemQuant) -> m UseResult
tryApplyEmbed (ItemId
iid, ItemQuant
kit)
let useResult = UseResult -> Maybe UseResult -> UseResult
forall a. a -> Maybe a -> a
fromMaybe UseResult
UseDud Maybe UseResult
museResult
processTileActions (Just $ max useResult triggered) rest
ToAction GroupName TileKind
tgroup -> Bool -> m Bool -> m Bool
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Bool -> Bool
not (Actor -> Bool
bproj Actor
sb)) (m Bool -> m Bool) -> m Bool -> m Bool
forall a b. (a -> b) -> a -> b
$
if Bool -> (UseResult -> Bool) -> Maybe UseResult -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
True (UseResult -> UseResult -> Bool
forall a. Eq a => a -> a -> Bool
== UseResult
UseUp) Maybe UseResult
museResult
then do
m ()
announceTileChange
GroupName TileKind -> m ()
changeTo GroupName TileKind
tgroup
Bool -> m Bool
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
else Maybe UseResult -> [TileAction] -> m Bool
processTileActions Maybe UseResult
museResult [TileAction]
rest
WithAction [(Int, GroupName ItemKind)]
grps GroupName TileKind
tgroup -> do
groundBag2 <- (State -> EnumMap ItemId ItemQuant) -> m (EnumMap ItemId ItemQuant)
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> EnumMap ItemId ItemQuant)
-> m (EnumMap ItemId ItemQuant))
-> (State -> EnumMap ItemId ItemQuant)
-> m (EnumMap ItemId ItemQuant)
forall a b. (a -> b) -> a -> b
$ Actor -> CStore -> State -> EnumMap ItemId ItemQuant
getBodyStoreBag Actor
sb CStore
CGround
eqpBag2 <- getsState $ getBodyStoreBag sb CEqp
if (not bumping || null grps)
&& (bproj sb || voluntary || null grps)
&& (maybe True (== UseUp) museResult
|| effToUse == EffOnCombine)
&& let f (a
k1, b
_) (a
k2, b
_) = a
k1 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
k2
in EM.isSubmapOfBy f groundBag groundBag2
&& EM.isSubmapOfBy f eqpBag eqpBag2
then do
altered <- tryChangeWith (grps, tgroup)
if altered
then return True
else processTileActions museResult rest
else processTileActions museResult rest
if null tileActions then
return $! if blockedByItem
&& not underFeet
&& Tile.isModifiable coTileSpeedup serverTile
then Just AlterBlockItem
else Just AlterNothing
else
if underFeet || not (occupiedBigLvl tpos lvl)
&& not (occupiedProjLvl tpos lvl) then do
revealEmbeds
tileTriggered <- processTileActions Nothing tileActions
let potentiallyMissing = ([(Int, GroupName ItemKind)] -> Bool)
-> [[(Int, GroupName ItemKind)]] -> [[(Int, GroupName ItemKind)]]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool)
-> ([(Int, GroupName ItemKind)] -> Bool)
-> [(Int, GroupName ItemKind)]
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(Int, GroupName ItemKind)] -> Bool
forall a. [a] -> Bool
null) [[(Int, GroupName ItemKind)]]
groupsToAlterWith
when (not tileTriggered && not underFeet && voluntary
&& not (null potentiallyMissing)) $
execSfxAtomic $ SfxMsgFid (bfid sb)
$ SfxNoItemsForTile potentiallyMissing
return Nothing
else return $ Just AlterBlockActor
reqWait :: MonadServerAtomic m => ActorId -> m ()
{-# INLINE reqWait #-}
reqWait :: forall (m :: * -> *). MonadServerAtomic m => ActorId -> m ()
reqWait ActorId
source = do
actorSk <- ActorId -> m Skills
forall (m :: * -> *). MonadServer m => ActorId -> m Skills
currentSkillsServer ActorId
source
unless (Ability.getSk Ability.SkWait actorSk > 0) $
execFailure source ReqWait WaitUnskilled
reqWait10 :: MonadServerAtomic m => ActorId -> m ()
{-# INLINE reqWait10 #-}
reqWait10 :: forall (m :: * -> *). MonadServerAtomic m => ActorId -> m ()
reqWait10 ActorId
source = do
actorSk <- ActorId -> m Skills
forall (m :: * -> *). MonadServer m => ActorId -> m Skills
currentSkillsServer ActorId
source
unless (Ability.getSk Ability.SkWait actorSk >= 4) $
execFailure source ReqWait10 WaitUnskilled
reqYell :: MonadServerAtomic m => ActorId -> m ()
reqYell :: forall (m :: * -> *). MonadServerAtomic m => ActorId -> m ()
reqYell ActorId
aid = do
actorSk <- ActorId -> m Skills
forall (m :: * -> *). MonadServer m => ActorId -> m Skills
currentSkillsServer ActorId
aid
if | Ability.getSk Ability.SkWait actorSk > 0 ->
execSfxAtomic $ SfxTaunt True aid
| Ability.getSk Ability.SkMove actorSk <= 0
|| Ability.getSk Ability.SkDisplace actorSk <= 0
|| Ability.getSk Ability.SkMelee actorSk <= 0 ->
execSfxAtomic $ SfxTaunt False aid
| otherwise -> do
b <- getsState $ getActorBody aid
case bwatch b of
WWait Int
_ -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Watchfulness
_ -> UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId -> Watchfulness -> Watchfulness -> UpdAtomic
UpdWaitActor ActorId
aid (Actor -> Watchfulness
bwatch Actor
b) (Int -> Watchfulness
WWait Int
0)
reqMoveItems :: MonadServerAtomic m
=> ActorId -> [(ItemId, Int, CStore, CStore)] -> m ()
reqMoveItems :: forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> [(ItemId, Int, CStore, CStore)] -> m ()
reqMoveItems ActorId
source [(ItemId, Int, CStore, CStore)]
l = do
actorSk <- ActorId -> m Skills
forall (m :: * -> *). MonadServer m => ActorId -> m Skills
currentSkillsServer ActorId
source
if Ability.getSk Ability.SkMoveItem actorSk > 0 then do
b <- getsState $ getActorBody source
actorMaxSk <- getsState $ getActorMaxSkills source
let calmE = Actor -> Skills -> Bool
calmEnough Actor
b Skills
actorMaxSk
case l of
[] -> ActorId -> RequestTimed -> ReqFailure -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> RequestTimed -> ReqFailure -> m ()
execFailure ActorId
source ([(ItemId, Int, CStore, CStore)] -> RequestTimed
ReqMoveItems [(ItemId, Int, CStore, CStore)]
l) ReqFailure
ItemNothing
(ItemId, Int, CStore, CStore)
iid : [(ItemId, Int, CStore, CStore)]
rest -> do
Bool -> ActorId -> Bool -> (ItemId, Int, CStore, CStore) -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
Bool -> ActorId -> Bool -> (ItemId, Int, CStore, CStore) -> m ()
reqMoveItem Bool
False ActorId
source Bool
calmE (ItemId, Int, CStore, CStore)
iid
((ItemId, Int, CStore, CStore) -> m ())
-> [(ItemId, Int, CStore, CStore)] -> m ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
(a -> m ()) -> t a -> m ()
mapM_ (Bool -> ActorId -> Bool -> (ItemId, Int, CStore, CStore) -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
Bool -> ActorId -> Bool -> (ItemId, Int, CStore, CStore) -> m ()
reqMoveItem Bool
True ActorId
source Bool
calmE) [(ItemId, Int, CStore, CStore)]
rest
else execFailure source (ReqMoveItems l) MoveItemUnskilled
reqMoveItem :: MonadServerAtomic m
=> Bool -> ActorId -> Bool -> (ItemId, Int, CStore, CStore) -> m ()
reqMoveItem :: forall (m :: * -> *).
MonadServerAtomic m =>
Bool -> ActorId -> Bool -> (ItemId, Int, CStore, CStore) -> m ()
reqMoveItem Bool
absentPermitted ActorId
aid Bool
calmE (ItemId
iid, Int
kOld, CStore
fromCStore, CStore
toCStore) = do
b <- (State -> Actor) -> m Actor
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> Actor) -> m Actor) -> (State -> Actor) -> m Actor
forall a b. (a -> b) -> a -> b
$ ActorId -> State -> Actor
getActorBody ActorId
aid
let fromC = ActorId -> CStore -> Container
CActor ActorId
aid CStore
fromCStore
req = [(ItemId, Int, CStore, CStore)] -> RequestTimed
ReqMoveItems [(ItemId
iid, Int
kOld, CStore
fromCStore, CStore
toCStore)]
toC <- case toCStore of
CStore
CGround -> Bool -> ActorId -> Actor -> m Container
forall (m :: * -> *).
MonadStateRead m =>
Bool -> ActorId -> Actor -> m Container
pickDroppable Bool
False ActorId
aid Actor
b
CStore
_ -> Container -> m Container
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Container -> m Container) -> Container -> m Container
forall a b. (a -> b) -> a -> b
$! ActorId -> CStore -> Container
CActor ActorId
aid CStore
toCStore
bagFrom <- getsState $ getContainerBag (CActor aid fromCStore)
bagBefore <- getsState $ getContainerBag toC
let k = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
kOld (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ ItemQuant -> Int
forall a b. (a, b) -> a
fst (ItemQuant -> Int) -> ItemQuant -> Int
forall a b. (a -> b) -> a -> b
$ ItemQuant -> ItemId -> EnumMap ItemId ItemQuant -> ItemQuant
forall k a. Enum k => a -> k -> EnumMap k a -> a
EM.findWithDefault (Int
0, []) ItemId
iid EnumMap ItemId ItemQuant
bagFrom
let !_A = Bool
absentPermitted Bool -> Bool -> Bool
|| Int
k Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
kOld
if
| absentPermitted && k == 0 -> return ()
| k < 1 || fromCStore == toCStore -> execFailure aid req ItemNothing
| fromCStore == CEqp && not calmE ->
execFailure aid req ItemNotCalm
| toCStore == CEqp && not calmE ->
execFailure aid req ItemNotCalm
| toCStore == CEqp && eqpOverfull b k ->
execFailure aid req EqpOverfull
| otherwise -> do
upds <- generalMoveItem True iid k fromC toC
mapM_ execUpdAtomic upds
itemFull <- getsState $ itemToFull iid
discoverIfMinorEffects toC iid (itemKindId itemFull)
when (toCStore `elem` [CEqp, COrgan]
&& fromCStore `notElem` [CEqp, COrgan]
|| fromCStore == CStash) $ do
let beforeIt = case ItemId
iid ItemId -> EnumMap ItemId ItemQuant -> Maybe ItemQuant
forall k a. Enum k => k -> EnumMap k a -> Maybe a
`EM.lookup` EnumMap ItemId ItemQuant
bagBefore of
Maybe ItemQuant
Nothing -> []
Just (Int
_, [ItemTimer]
it2) -> [ItemTimer]
it2
randomResetTimeout k iid itemFull beforeIt toC
reqProject :: MonadServerAtomic m
=> ActorId
-> Point
-> Int
-> ItemId
-> CStore
-> m ()
reqProject :: forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> Point -> Int -> ItemId -> CStore -> m ()
reqProject ActorId
source Point
tpxy Int
eps ItemId
iid CStore
cstore = do
let req :: RequestTimed
req = Point -> Int -> ItemId -> CStore -> RequestTimed
ReqProject Point
tpxy Int
eps ItemId
iid CStore
cstore
b <- (State -> Actor) -> m Actor
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> Actor) -> m Actor) -> (State -> Actor) -> m Actor
forall a b. (a -> b) -> a -> b
$ ActorId -> State -> Actor
getActorBody ActorId
source
curChalSer <- getsServer $ scurChalSer . soptions
fact <- getsState $ (EM.! bfid b) . sfactionD
actorMaxSk <- getsState $ getActorMaxSkills source
let calmE = Actor -> Skills -> Bool
calmEnough Actor
b Skills
actorMaxSk
if | ckeeper curChalSer && fhasUI (gkind fact) ->
execFailure source req ProjectFinderKeeper
| cstore == CEqp && not calmE -> execFailure source req ItemNotCalm
| otherwise -> do
mfail <-
projectFail source source (bpos b) tpxy eps False iid cstore False
maybe (return ()) (execFailure source req) mfail
reqApply :: MonadServerAtomic m
=> ActorId
-> ItemId
-> CStore
-> m ()
reqApply :: forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> ItemId -> CStore -> m ()
reqApply ActorId
aid ItemId
iid CStore
cstore = do
COps{corule} <- (State -> COps) -> m COps
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState State -> COps
scops
let req = ItemId -> CStore -> RequestTimed
ReqApply ItemId
iid CStore
cstore
b <- getsState $ getActorBody aid
actorMaxSk <- getsState $ getActorMaxSkills aid
let calmE = Actor -> Skills -> Bool
calmEnough Actor
b Skills
actorMaxSk
if cstore == CEqp && not calmE then execFailure aid req ItemNotCalm
else do
bag <- getsState $ getBodyStoreBag b cstore
case EM.lookup iid bag of
Maybe ItemQuant
Nothing -> ActorId -> RequestTimed -> ReqFailure -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> RequestTimed -> ReqFailure -> m ()
execFailure ActorId
aid RequestTimed
req ReqFailure
ApplyOutOfReach
Just ItemQuant
kit -> do
itemFull <- (State -> ItemFull) -> m ItemFull
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> ItemFull) -> m ItemFull)
-> (State -> ItemFull) -> m ItemFull
forall a b. (a -> b) -> a -> b
$ ItemId -> State -> ItemFull
itemToFull ItemId
iid
actorSk <- currentSkillsServer aid
localTime <- getsState $ getLocalTime (blid b)
let skill = Skill -> Skills -> Int
Ability.getSk Skill
Ability.SkApply Skills
actorSk
legal = RuleContent
-> Time
-> Int
-> Bool
-> Maybe CStore
-> ItemFull
-> ItemQuant
-> Either ReqFailure Bool
permittedApply RuleContent
corule Time
localTime Int
skill Bool
calmE (CStore -> Maybe CStore
forall a. a -> Maybe a
Just CStore
cstore)
ItemFull
itemFull ItemQuant
kit
case legal of
Left ReqFailure
reqFail -> ActorId -> RequestTimed -> ReqFailure -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> RequestTimed -> ReqFailure -> m ()
execFailure ActorId
aid RequestTimed
req ReqFailure
reqFail
Right Bool
_ -> ActorId -> ItemId -> CStore -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> ItemId -> CStore -> m ()
applyItem ActorId
aid ItemId
iid CStore
cstore
reqGameRestart :: MonadServerAtomic m
=> ActorId -> GroupName ModeKind -> Challenge
-> m ()
reqGameRestart :: forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> GroupName ModeKind -> Challenge -> m ()
reqGameRestart ActorId
aid GroupName ModeKind
groupName Challenge
scurChalSer = do
noConfirmsGame <- m Bool
forall (m :: * -> *). MonadStateRead m => m Bool
isNoConfirmsGame
factionD <- getsState sfactionD
let fidsUI = ((FactionId, Faction) -> FactionId)
-> [(FactionId, Faction)] -> [FactionId]
forall a b. (a -> b) -> [a] -> [b]
map (FactionId, Faction) -> FactionId
forall a b. (a, b) -> a
fst ([(FactionId, Faction)] -> [FactionId])
-> [(FactionId, Faction)] -> [FactionId]
forall a b. (a -> b) -> a -> b
$ ((FactionId, Faction) -> Bool)
-> [(FactionId, Faction)] -> [(FactionId, Faction)]
forall a. (a -> Bool) -> [a] -> [a]
filter (\(FactionId
_, Faction
fact) -> FactionKind -> Bool
fhasUI (Faction -> FactionKind
gkind Faction
fact))
(FactionDict -> [(FactionId, Faction)]
forall k a. Enum k => EnumMap k a -> [(k, a)]
EM.assocs FactionDict
factionD)
unless noConfirmsGame $
mapM_ revealAll fidsUI
b <- getsState $ getActorBody aid
oldSt <- getsState $ gquit . (EM.! bfid b) . sfactionD
factionAn <- getsServer sfactionAn
generationAn <- getsServer sgenerationAn
execUpdAtomic $ UpdQuitFaction
(bfid b)
oldSt
(Just $ Status Restart (fromEnum $ blid b) (Just groupName))
(Just (factionAn, generationAn))
modifyServer $ \StateServer
ser -> StateServer
ser { sbreakASAP = True
, soptionsNxt = (soptionsNxt ser) {scurChalSer} }
reqGameDropAndExit :: MonadServerAtomic m => ActorId -> m ()
reqGameDropAndExit :: forall (m :: * -> *). MonadServerAtomic m => ActorId -> m ()
reqGameDropAndExit ActorId
aid = do
m ()
forall (m :: * -> *). MonadServer m => m ()
verifyAssertExplored
b <- (State -> Actor) -> m Actor
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> Actor) -> m Actor) -> (State -> Actor) -> m Actor
forall a b. (a -> b) -> a -> b
$ ActorId -> State -> Actor
getActorBody ActorId
aid
oldSt <- getsState $ gquit . (EM.! bfid b) . sfactionD
execUpdAtomic $ UpdQuitFaction
(bfid b)
oldSt
(Just $ Status Camping (fromEnum $ blid b) Nothing)
Nothing
modifyServer $ \StateServer
ser -> StateServer
ser { sbreakASAP = True
, sbreakLoop = True }
verifyAssertExplored :: MonadServer m => m ()
verifyAssertExplored :: forall (m :: * -> *). MonadServer m => m ()
verifyAssertExplored = do
assertExplored <- (StateServer -> Maybe Int) -> m (Maybe Int)
forall a. (StateServer -> a) -> m a
forall (m :: * -> *) a. MonadServer m => (StateServer -> a) -> m a
getsServer ((StateServer -> Maybe Int) -> m (Maybe Int))
-> (StateServer -> Maybe Int) -> m (Maybe Int)
forall a b. (a -> b) -> a -> b
$ ServerOptions -> Maybe Int
sassertExplored (ServerOptions -> Maybe Int)
-> (StateServer -> ServerOptions) -> StateServer -> Maybe Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StateServer -> ServerOptions
soptions
case assertExplored of
Maybe Int
Nothing -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Just Int
lvlN -> do
snumSpawned <- (StateServer -> EnumMap LevelId Int) -> m (EnumMap LevelId Int)
forall a. (StateServer -> a) -> m a
forall (m :: * -> *) a. MonadServer m => (StateServer -> a) -> m a
getsServer StateServer -> EnumMap LevelId Int
snumSpawned
let !_A = Bool -> () -> ()
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Int -> LevelId
forall a. Enum a => Int -> a
toEnum Int
lvlN LevelId -> EnumMap LevelId Int -> Bool
forall k a. Enum k => k -> EnumMap k a -> Bool
`EM.member` EnumMap LevelId Int
snumSpawned
Bool -> Bool -> Bool
|| Int -> LevelId
forall a. Enum a => Int -> a
toEnum (- Int
lvlN) LevelId -> EnumMap LevelId Int -> Bool
forall k a. Enum k => k -> EnumMap k a -> Bool
`EM.member` EnumMap LevelId Int
snumSpawned
Bool -> (String, Int) -> Bool
forall v. Show v => Bool -> v -> Bool
`blame` String
"by game end, exploration haven't reached the expected level depth, indicating stuck AI (or just very busy initial levels)"
String -> Int -> (String, Int)
forall v. String -> v -> (String, v)
`swith` Int
lvlN) ()
return ()
reqGameSaveAndExit :: MonadServerAtomic m => ActorId -> m ()
reqGameSaveAndExit :: forall (m :: * -> *). MonadServerAtomic m => ActorId -> m ()
reqGameSaveAndExit ActorId
aid = do
m ()
forall (m :: * -> *). MonadServer m => m ()
verifyAssertExplored
b <- (State -> Actor) -> m Actor
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> Actor) -> m Actor) -> (State -> Actor) -> m Actor
forall a b. (a -> b) -> a -> b
$ ActorId -> State -> Actor
getActorBody ActorId
aid
oldSt <- getsState $ gquit . (EM.! bfid b) . sfactionD
execUpdAtomic $ UpdQuitFaction
(bfid b)
oldSt
(Just $ Status Camping (fromEnum $ blid b) Nothing)
Nothing
modifyServer $ \StateServer
ser -> StateServer
ser { sbreakASAP = True
, swriteSave = True }
reqGameSave :: MonadServer m => m ()
reqGameSave :: forall (m :: * -> *). MonadServer m => m ()
reqGameSave =
(StateServer -> StateServer) -> m ()
forall (m :: * -> *).
MonadServer m =>
(StateServer -> StateServer) -> m ()
modifyServer ((StateServer -> StateServer) -> m ())
-> (StateServer -> StateServer) -> m ()
forall a b. (a -> b) -> a -> b
$ \StateServer
ser -> StateServer
ser { sbreakASAP = True
, swriteSave = True }
reqDoctrine :: MonadServerAtomic m => FactionId -> Ability.Doctrine -> m ()
reqDoctrine :: forall (m :: * -> *).
MonadServerAtomic m =>
FactionId -> Doctrine -> m ()
reqDoctrine FactionId
fid Doctrine
toT = do
fromT <- (State -> Doctrine) -> m Doctrine
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> Doctrine) -> m Doctrine)
-> (State -> Doctrine) -> m Doctrine
forall a b. (a -> b) -> a -> b
$ Faction -> Doctrine
gdoctrine (Faction -> Doctrine) -> (State -> Faction) -> State -> Doctrine
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FactionDict -> FactionId -> Faction
forall k a. Enum k => EnumMap k a -> k -> a
EM.! FactionId
fid) (FactionDict -> Faction)
-> (State -> FactionDict) -> State -> Faction
forall b c a. (b -> c) -> (a -> b) -> a -> c
. State -> FactionDict
sfactionD
execUpdAtomic $ UpdDoctrineFaction fid toT fromT
reqAutomate :: MonadServerAtomic m => FactionId -> m ()
reqAutomate :: forall (m :: * -> *). MonadServerAtomic m => FactionId -> m ()
reqAutomate FactionId
fid = UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ FactionId -> Bool -> UpdAtomic
UpdAutoFaction FactionId
fid Bool
True