Files
loop/src/Dodge/Data.hs
T

695 lines
21 KiB
Haskell

{- |
Contains base datatypes that cannot be seperated into
different modules because they are interdependent;
circular imports are probably not a good idea.
-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE StrictData #-}
{-# LANGUAGE DeriveGeneric #-}
module Dodge.Data
( module Dodge.Data
, module Dodge.Data.DamageType
, module Dodge.Data.SoundOrigin
, Point2
, Sound (..)
, soundTime
) where
import Dodge.Creature.State.Data
import Dodge.Creature.Stance.Data
import Dodge.Creature.AlertLevel.Data
import Dodge.Debug.Flag.Data
import Dodge.Data.Menu
import Dodge.Data.SoundOrigin
import Dodge.Data.DamageType
import Dodge.Config.Data
import Dodge.Config.KeyConfig
import Dodge.Item.Attachment.Data
import Dodge.Item.Data
import Dodge.World.Trigger.Data
import Preload.Data
import Picture.Data
import Geometry.Data
import Sound.Data
import qualified DoubleStack as DS
import GHC.Generics
import Control.Lens
import System.Random
import Data.Graph.Inductive
import Data.Int (Int16)
import qualified Data.Set as S
import qualified Data.IntSet as IS
import qualified Data.IntMap.Strict as IM
import qualified Data.Map as M
import SDL (Scancode, MouseButton)
data World = World
{ _keys :: !(S.Set Scancode)
, _mouseButtons :: !(S.Set MouseButton)
, _cameraCenter :: !Point2
, _cameraRot :: !Float
, _cameraZoom :: !Float
, _cameraViewFrom :: !Point2
, _creatures :: IM.IntMap Creature
, _creaturesZone :: IM.IntMap (IM.IntMap (IM.IntMap Creature))
, _creatureGroups :: IM.IntMap CrGroupParams
, _itemPositions :: IM.IntMap ItemPos
, _clouds :: IM.IntMap Cloud
, _cloudsZone :: IM.IntMap (IM.IntMap (IM.IntMap Cloud))
, _projectiles :: IM.IntMap Projectile
, _particles :: ![Particle]
, _staticWalls :: [Wall]
, _walls :: !(IM.IntMap Wall)
, _wallsZone :: IM.IntMap (IM.IntMap (IM.IntMap Wall))
, _forceFields :: IM.IntMap ForceField
, _floorItems :: IM.IntMap FloorItem
, _randGen :: StdGen
, _mousePos :: !(Float,Float)
, _testString :: String
, _yourID :: !Int
, _worldEvents :: !(World -> World)
, _pressPlates :: IM.IntMap PressPlate
, _buttons :: IM.IntMap Button
, _soundQueue :: [(Int,Int16)]
, _sounds :: M.Map SoundOrigin Sound
, _decorations :: IM.IntMap Picture
, _foregroundDecorations :: [Picture]
, _corpses :: IM.IntMap (IM.IntMap [Corpse])
, _clickMousePos :: (Float,Float)
, _pathGraph :: ~(Gr Point2 Float)
, _pathGraph' :: ~[(Point2,Point2)]
, _pathPoints :: ~(IM.IntMap (IM.IntMap [(Int,Point2)]))
, _pathInc :: ~(M.Map Point2 [Point2])
, _storedLevel :: Maybe World
, _menuLayers :: [MenuLayer]
, _worldState :: M.Map WorldState Bool
, _worldTriggers :: S.Set WorldTrigger
, _carteDisplay :: !Bool
, _carteCenter :: !Point2
, _carteZoom :: !Float
, _carteRot :: !Float
, _lightSources :: !(IM.IntMap LightSource)
, _tempLightSources :: ![TempLightSource]
, _closeActiveObjects :: [Either FloorItem Button]
, _seenLocations :: IM.IntMap (World -> Point2,String)
, _selLocation :: Int
, _keyConfig :: KeyConfigSDL
, _config :: Configuration
, _sideEffects :: [PreloadData SoundOrigin -> IO (PreloadData SoundOrigin)]
, _doneSideEffects :: [PreloadData SoundOrigin -> IO (PreloadData SoundOrigin)]
, _debugFlags :: DebugFlags
, _inventoryMode :: InventoryMode
, _lClickHammer :: HammerPosition
}
data InventoryMode
= TopInventory
| TweakInventory
| CombineInventory
| InspectInventory
deriving (Eq, Ord, Show)
data CrGroupParams = CrGroupParams
{ _crGroupParamID :: Int
, _crGroupIDs :: IS.IntSet
, _crGroupCenter :: Point2
, _crGroupUpdate :: World -> CrGroupParams -> Maybe CrGroupParams
}
data Corpse = Corpse
{ _cpPos :: Point2
, _cpPict :: Picture
, _cpRes :: Creature
}
data Cloud = Cloud
{ _clID :: Int
, _clPos :: Point2
, _clVel :: Point2
, _clPict :: Cloud -> Picture
, _clRad :: Float
, _clTimer :: Int
, _clEffect :: Cloud -> World -> World
}
data LightSource = LS
{ _lsID :: !Int
, _lsPos :: !Point2
, _lsDir :: !Float
, _lsRad :: !Float
, _lsIntensity :: !Float
}
data TempLightSource = TLS
{ _tlsPos :: !Point2
, _tlsRad :: !Float
, _tlsIntensity :: !Float
, _tlsUpdate :: World -> TempLightSource -> (World, Maybe TempLightSource)
}
data Creature = Creature
{ _crPos :: Point2
, _crOldPos :: Point2
, _crVel :: Point2
, _crDir :: Float
, _crMvDir :: Float
, _crID :: Int
, _crPict :: Creature -> World -> Picture
, _crUpdate
:: World
-> (World -> World,StdGen)
-> Creature
-> ((World -> World,StdGen), Maybe Creature)
, _crRad :: Float
, _crMass :: Float
, _crHP :: Int
, _crMaxHP :: Int
, _crInv :: IM.IntMap Item
, _crInvSel :: Int
, _crLeftInvSel :: Maybe Int
, _crState :: CreatureState
, _crCorpse :: Picture
, _crApplyDamage :: [DamageType] -> Creature -> (World -> World,Creature)
, _crStance :: Stance
, _crActionPlan :: ActionPlan
, _crMeleeCooldown :: Maybe Int
, _crAwakeLevel :: AwakeLevel
, _crAttentionDir :: AttentionDir
, _crAwarenessLevel :: IM.IntMap AwarenessLevel
, _crFaction :: Faction
, _crGroup :: CrGroup
, _crTarget :: Maybe Creature
}
data WorldState
= DoorNumOpen Int
| CrNumAlive Int
deriving (Eq,Ord)
data Button = Button
{ _btPict :: Picture
, _btPos :: Point2
, _btRot :: Float
, _btEvent :: Button -> World -> World
, _btID :: Int
, _btText :: String
, _btState :: ButtonState
}
data ButtonState = BtOn | BtOff | BtNoLabel
deriving (Eq, Show)
data PressPlate = PressPlate
{ _ppPict :: Picture
, _ppPos :: Point2
, _ppRot :: Float
, _ppEvent :: PressPlate -> World -> World
, _ppID :: Int
, _ppText :: String
}
data FloorItem = FlIt { _flIt :: Item , _flItPos :: Point2 , _flItRot :: Float, _flItID :: Int}
data ItemPos
= InInv { _itCrId :: Int , _itInvId :: Int }
| OnFloor { _itFlID :: Int }
data Item
= Weapon
{ _itName :: String
, _wpMaxAmmo :: Int
, _wpLoadedAmmo :: Int
, _wpAmmo :: Ammo
, _wpReloadTime :: Int
, _wpReloadState :: Int
, _itUseRate :: Int
, _itUseTime :: Int
, _itUse :: Item -> Creature -> World -> World
, _itUseModifiers :: [(Item -> Creature -> World -> World) -> Item -> Creature -> World -> World]
, _itLeftClickUse :: Maybe (Creature -> Int -> World -> World)
, _wpSpread :: Float
, _wpRange :: Float
, _itHammer :: HammerPosition
, _itFloorPict :: Picture
, _itMaxStack :: Int
, _itAmount :: Int
, _itAimingSpeed :: Float
, _itAimingRange :: Float
, _itZoom :: ItZoom
, _itEquipPict :: Creature -> Int -> Picture
, _itScroll :: Float -> Creature -> World -> World
, _itIdentity :: ItemIdentity
, _itAttachment :: Maybe ItAttachment
, _itID :: Maybe Int
, _itEffect :: ItEffect
, _itInvDisplay :: Item -> String
, _itInvColor :: Color
, _itTargeting :: Maybe (World -> Maybe Point2, Int -> Item -> Creature -> World -> Picture)
, _itWorldTrigger :: Maybe (Int -> World -> Bool)
, _itAimStance :: AimStance
}
| Consumable
{ _itName :: String
, _itMaxStack :: Int
, _itAmount :: Int
, _cnEffect :: Int -> World -> Maybe World
, _itFloorPict :: Picture
, _itEquipPict :: Creature -> Int -> Picture
, _itIdentity :: ItemIdentity
, _itID :: Maybe Int
, _itInvDisplay :: Item -> String
, _itInvColor :: Color
, _itEffect :: ItEffect
, _itHammer :: HammerPosition
, _itAimStance :: AimStance
}
| Craftable
{ _itName :: String
, _itMaxStack :: Int
, _itAmount :: Int
, _itFloorPict :: Picture
, _itEquipPict :: Creature -> Int -> Picture
, _itIdentity :: ItemIdentity
, _itID :: Maybe Int
, _itInvDisplay :: Item -> String
, _itInvColor :: Color
, _itAimStance :: AimStance
}
| Equipment
{ _itName :: String
, _itMaxStack :: Int
, _itAmount :: Int
, _itFloorPict :: Picture
, _itEquipPict :: Creature -> Int -> Picture
, _itIdentity :: ItemIdentity
, _itEffect :: ItEffect
, _itID :: Maybe Int
, _itAimingSpeed :: Float
, _itAimingRange :: Float
, _itZoom :: ItZoom
, _itInvDisplay :: Item -> String
, _itInvColor :: Color
, _itHammer :: HammerPosition
, _itAimStance :: AimStance
}
| Throwable
{ _itName :: String
, _itMaxStack :: Int
, _itAmount :: Int
, _itFloorPict :: Picture
, _twMaxRange :: Float
, _twAccuracy :: Float
, _itUse :: Item -> Creature -> World -> World
, _itUseRate :: Int
, _itUseTime :: Int
, _itAimingSpeed :: Float
, _itAimingRange :: Float
, _itZoom :: ItZoom
, _itEquipPict :: Creature -> Int -> Picture
, _itIdentity :: ItemIdentity
, _itID :: Maybe Int
, _itAttachment :: Maybe ItAttachment
, _itInvDisplay :: Item -> String
, _itInvColor :: Color
, _itEffect :: ItEffect
, _itHammer :: HammerPosition
, _itScrollUp :: Int -> World -> World
, _itScrollDown :: Int -> World -> World
, _itAimStance :: AimStance
}
| NoItem
data ItEffect = NoItEffect
| ItInvEffect
{_itInvEffect :: ItEffect -> Creature -> Int -> World -> World
-- the Int is the items inventory position
,_itEffectCounter :: Int
}
| ItEffect
{_itInvEffect :: ItEffect -> Creature -> Int -> World -> World
,_itFloorEffect :: Int -> World -> World
,_itEffectCounter :: Int
}
data ItZoom = ItZoom
{_itAimZoomMax :: Float
,_itAimZoomMin :: Float
,_itAimZoomFac :: Float
,_itZoomMax :: Float
,_itZoomMin :: Float
,_itZoomFac :: Float
}
data IntID a = IntID Int a
{- Objects without ids.
Update themselves, perhaps with side effects. -}
data Particle
= Particle
{ _ptDraw :: Particle -> Picture
, _ptUpdate' :: World -> Particle -> (World, Maybe Particle)
}
| LinearParticle
{ _ptDraw :: Particle -> Picture
, _ptUpdate' :: World -> Particle -> (World, Maybe Particle)
, _ptPoints :: [Point2]
, _ptTimer :: Int
, _ptColor :: Color
}
| Bul'
{ _ptDraw :: Particle -> Picture
, _ptUpdate' :: World -> Particle -> (World, Maybe Particle)
, _btVel' :: Point2
, _btColor' :: Color
, _btTrail' :: [Point2]
, _btPassThrough' :: Maybe Int
, _btWidth' :: Float
, _btTimer' :: Int
, _btHitEffect' :: HitEffect
}
| Pt'
{ _ptDraw :: Particle -> Picture
, _ptUpdate' :: World -> Particle -> (World, Maybe Particle)
, _btVel' :: Point2
, _btColor' :: Color
, _btPos' :: Point2
, _btPassThrough' :: Maybe Int
, _btWidth' :: Float
, _btTimer' :: Int
, _btHitEffect' :: HitEffect
}
| Shockwave'
{ _ptDraw :: Particle -> Picture
, _ptUpdate' :: World -> Particle -> (World, Maybe Particle)
, _btColor' :: Color
, _btPos' :: Point2
, _btRad' :: Float
, _btDam' :: Int
, _btPush' :: Float
, _btMaxTime' :: Int
, _btTimer' :: Int
}
type HitEffect = Particle
-> [(Point2, Either3 Creature Wall ForceField)]
-> World
-> (World,Maybe Particle)
data Ammo
= ShellAmmo
{ _amPayload :: Point2 -> World -> World
, _amString :: String
, _amPjParams :: [PjParam]
, _amPjDraw :: Projectile -> Picture
, _amParamSel :: Int
}
| BulletAmmo
{ _amString :: String
, _amBulEff :: HitEffect
, _amBulWth :: Float
, _amBulVel :: Point2
}
| GenericAmmo
data PjParam = PjParam
{ _pjMoveParam :: Int -> Item -> Creature -> Projectile -> World -> World
, _pjIntParam :: Int
, _pjMaxParam :: Int
, _pjDisplayParam :: Int -> String
}
data Projectile
= Projectile
{ _pjPos :: Point2
, _pjStartPos :: Point2
, _pjVel :: Point2
, _pjDraw :: Projectile -> Picture
, _pjID :: Int
, _pjUpdate :: Projectile -> World -> World
}
| Shell
{ _pjPos :: Point2
, _pjStartPos :: Point2
, _pjVel :: Point2
, _pjAcc :: Point2
, _pjDir :: Float
, _pjSpin :: Float
, _pjDraw :: Projectile -> Picture
, _pjID :: Int
, _pjUpdate :: Projectile -> World -> World
, _pjPayload :: Point2 -> World -> World
, _pjTimer :: Int
}
| LinearShockwave
{ _pjDraw :: Projectile -> Picture
, _pjID :: Int
, _pjUpdate :: Projectile -> World -> World
, _pjPoints :: [(Point2,Point2)]
, _pjTimer :: Int
}
data Either3 a b c = E3x1 a | E3x2 b | E3x3 c
data Wall
= Wall
{ _wlLine :: (Point2,Point2)
, _wlID :: Int
, _wlColor :: Color
, _wlSeen :: Bool
, _wlIsSeeThrough :: Bool
}
| BlockAutoDoor
{ _wlLine :: (Point2,Point2)
, _wlID :: Int
, _doorMech :: World -> World
, _wlColor :: Color
, _wlSeen :: Bool
, _blIDs :: [Int]
, _blHP :: Int
, _wlIsSeeThrough :: Bool
}
| Door
{ _wlLine :: (Point2,Point2)
, _wlID :: Int
, _doorMech :: World -> World
, _wlColor :: Color
, _wlSeen :: Bool
, _wlIsSeeThrough :: Bool
, _doorPathable :: Bool
, _drPositions :: DS.DS (Point2,Point2)
}
| Block
{ _wlLine :: (Point2,Point2)
, _wlID :: Int
, _wlColor :: Color
, _wlSeen :: Bool
, _blIDs :: [Int]
, _blHP :: Int
, _wlIsSeeThrough :: Bool
, _blVisible :: Bool
, _blDegrades :: [Int]
, _blShadows :: [Int]
}
data ForceField = FF
{ _ffLine :: [Point2] , _ffID :: Int
, _ffColor :: Color
, _ffDeflect :: Maybe (StdGen -> Point2 -> ForceField -> (Point2,StdGen))
, _ffState :: FFState
}
data FFState = FFDestroyable { _ffsHP :: Int }
data ActionPlan
= Inanimate
| ActionPlan
{_crImpulse :: [Impulse]
,_crAction :: [Action]
,_crStrategy :: Strategy
,_crGoal :: [Goal]
}
data Impulse
= Move Point2
| MoveForward Float
| StepForward
| Turn Float
| RandomTurn Float
| TurnToward Point2 Float
| TurnTo Point2
| UseItem
| SwitchToItem Int
| DropItem
| PickupNearby Int
| UseWorldObject Int
| Bark -- placeholder for various communication types
| UseIntrinsicAbility
| Melee Int
| ChangePosture Posture
| MakeSound Int
| ChangeStrategy Strategy
| AddGoal Goal
| ArbitraryImpulseFunction (World -> Creature -> Creature)
| ArbitraryImpulse (Creature -> World -> Impulse)
| ImpulseUseTargetCID
{_impulseUseTargetCID :: Int -> Impulse
}
| ImpulseUseTarget
{_impulseUseTarget :: Creature -> Impulse
}
| ImpulseUseAheadPos
{_impulseUseAheadPos :: Point2 -> Impulse
}
-- deriving (Eq,Ord,Show)
infixr 9 `WaitThen`
infixr 9 `DoActionThen`
infixr 9 `DoActionWhile`
infixr 9 `DoReplicate`
infixr 9 `DoImpulsesAlongside`
data Action
= Attack
{_attackTargetID :: Int}
| AimAtCloseSlow
{_targetID :: Int
,_targetSeenAt :: Point2
,_aimSpeed :: Float
,_slowAimSpeed :: Float
,_slowAimAngle :: Float
}
| MeleeAttack
{_meleeAttackLastSeen :: Point2
,_meleeAttackTargetID :: Int
}
| PathTo
{_pathToPoint :: Point2
}
| HealSelf
| DefendSelf
| Protect
{_protectCID :: Int
}
| SearchFor
{_searchForCID :: Int
}
| Search
| PickupItem
{_pickupItemID :: Int
}
| ImpulsesList
{_impulsesListList :: [[Impulse]]
}
| DoImpulses
{_doImpulsesList :: [Impulse]
}
| WaitThen
{_waitThenTimer :: Int
,_waitThenAction :: Action
}
| DoActionWhile
{_doActionWhileCondition :: (World, Creature) -> Bool
,_doActionWhileAction :: Action
}
| DoActionWhilePartial
{_doActionWhilePartial :: Action
,_doActionWhileCondition :: (World, Creature) -> Bool
,_doActionWhileAction :: Action
}
| DoActionIf
{_doActionIfCondition :: (World, Creature) -> Bool
,_doActionIfAction :: Action
}
| DoActionIfElse
{_doActionIfElseIfAction :: Action
,_doActionIfElseCondition :: (World, Creature) -> Bool
,_doActionIfElseElseAction :: Action
}
| DoActionWhileInterrupt
{_doActionWhileThenDo :: Action
,_doActionWhileThenCondition :: (World, Creature) -> Bool
,_doActionWhileThenThen :: Action
}
| DoActions
{_doActionsList :: [Action]
}
| DoActionOnce
{_doActionOnceAction :: Action
}
| DoActionThen
{_doActionThenFirst :: Action
,_doActionThenSecond :: Action
}
| DoGuardActions
{_doGuardActionsList :: [( (World, Creature) -> Bool, Action, Maybe Action)]
}
| DoReplicate
{_doReplicateTimes :: Int
,_doReplicateAction :: Action
}
| DoReplicatePartial
{_partialAction :: Action
,_doReplicateTimes :: Int
,_doReplicateAction :: Action
}
| LeadTarget
{_leadTargetBy :: Point2
}
| NoAction
| StartSentinelPost
| UseTarget
{_useTarget :: Maybe Creature -> Action
}
| UseTargetCID
{_useTargetCID :: Int -> Action
}
| UseSelf
{_useSelf :: Creature -> Action
}
| UseAheadPos
{_useAheadPos :: Point2 -> Action
}
| ArbitraryAction
{ _arbitraryAction :: Creature -> World -> Action }
| DoActionAlongside -- ^ Repeatedly perform a side action alongside a main action until the main action terminates
{_sideAction :: Action
,_mainAction :: Action
}
| DoImpulsesAlongside -- ^ Repeatedly perform impulses alongside a main action until the main action terminates
{_sideImpulses :: [Impulse]
,_mainAction :: Action
}
deriving (Generic)
-- deriving (Eq,Ord,Show)
data Strategy
= Flank Int
| Ambush Int
| Lure Int Point2
| Patrol [Point2]
| ShootAt Int
| FollowImpulses
| WatchAndWait
| StrategyActions Strategy [Action]
| GetTo Point2
| Reload
| Flee
| MeleeStrike
deriving (Generic)
-- deriving (Eq,Ord,Show)
data Goal
= LiveLongAndProsper
| Kill Int
| SentinelAt Point2 Float
makeLenses ''World
makeLenses ''Cloud
makeLenses ''Creature
makeLenses ''LightSource
makeLenses ''TempLightSource
makeLenses ''Item
makeLenses ''ItemPos
makeLenses ''ItEffect
makeLenses ''ItZoom
makeLenses ''FloorItem
makeLenses ''Ammo
makeLenses ''PjParam
makeLenses ''Projectile
makeLenses ''Particle
makeLenses ''Wall
makeLenses ''ForceField
makeLenses ''FFState
makeLenses ''PressPlate
makeLenses ''Button
makeLenses ''ActionPlan
makeLenses ''Impulse
makeLenses ''Action
makeLenses ''CrGroupParams
numColor :: Int -> Color
numColor 0 = (1,0,0,1)
numColor 1 = (0,1,0,1)
numColor 2 = (0,0,1,1)
numColor 3 = (1,1,0,1)
numColor 4 = (0,1,1,1)
numColor 5 = (1,0,1,1)
numColor 6 = (1,0,0.5,1)
numColor 7 = (0.5,0,1,1)
numColor 8 = (0,0.5,1,1)
numColor 9 = (0,1,0.5,1)
numColor 10 = (0.5,1,0,1)
numColor 11 = (1,0.5,0,1)
numColor 12 = (1,1,1,1)
numColor _ = (1,1,1,1)