================================================================================
Killing Time Defs Reference
================================================================================

v1.0 2024/10/22

--------------------------------------------------------------------------------
Actors - defs/actors.json
--------------------------------------------------------------------------------

Defines static shared data for types of actors. At runtime, actors are instances
of the Actor subclass of Thinker. The actor JSON definition is reflected as a
constant ActorInfo object, which can be obtained in scripting by a statement 
like the following (given Actor @actor):

   const ActorInfo @info = actor.GetActorInfo();
   
This handle can never be null.

Note that a valid actor type must be specified as the player's spawn actor in 
player.json or the game will not allow levels to be loaded at all.

The actors.json file should be an array of one or more objects of the following
schema:

   {
      // IDs
      "name"  : string, // name for lookups, must be unique
      "ednum" : uint,   // editor number (default 0 means cannot be spawned in maps)

      // Metrics
      "radius"       : integer,  // half-width of actor (default 0)
      "height"       : integer,  // height of actor (default 0)
      "spawnhealth"  : integer,  // initial health (default 0)
      "painchance"   : integer,  // chance for pain (out of 255) when damaged (default 0)
      "mass"         : integer,  // affects distance moved when thrust is applied (default 0)
      "speed"        : integer,  // speed of actor (default 0)
      "reactiontime" : integer,  // wait tics before attack/after teleport (default 0)
      "damage"       : integer,  // damage factor (dependent on use in scripting) (default 0)
      "selfdamage"   : float,    // self-damage factor (default 1.0)
      "alpha"        : byte,     // alpha (default 127)
      "gravity"      : float,    // gravity factor (default 1.0)

      // States
      "spawnstate"       : string, // actor spawns in this state (default empty)
      "seestate"         : string, // awakened actor jumps to this state (default empty)
      "painstate"        : string, // damaged actor may jump to this state (default empty)
      "meleestate"       : string, // actor up-close attack state (default empty)
      "missilestate"     : string, // actor distance attack state (default empty)
      "deathstate"       : string, // dying actor jumps to this state (default empty)
      "lastdeathstate"   : string, // final death state; used when changing res mode if set (default empty)
      "itemrespawnstate" : string, // item respawn state (default empty)
      "itemremovestate"  : string, // item remove state (default empty)
      "cinderstate"      : string, // alternate death state when burned by flames if not empty (default empty)

      "cachesprites" : // extra sprites to cache during spawn - array of array of strings
      [
         [ "Spritename", "mode" ], 
         ...
      ],
      /*
         "mode" explanations: 
         "toggled"   - sprite automatically adds "3DO/" to its file path if hires mode is enabled
         "hi_only"   - this entry is only cached if actors are in hi-res mode
         "Lo_only"   - this entry is only cached if actors are in low-res mode
         "altstates" - cache sprite in thing's alt spawnstate if hires mode is enabled
         
         WARNING: unlike most definition string values these values are treated 
         as CASE SENSITIVE and will not work if not spelled exactly as above.
      */

      // Sounds
      "seesound"     : string, // made when actor is alerted (default empty)
      "attacksound"  : string, // used when actor attacks (default empty)
      "painsound"    : string, // used when actor feels pain (default empty)
      "deathsound"   : string, // used when actor dies (default empty)
      "activesound"  : string, // used when actor roams (default empty)
      "paintactile"  : string, // pain tactile data; only for player (default empty)
      "deathtactile" : string, // death tactile data; only for player (default empty)

      "seesoundhi"    : string, // alternate sounds for 3DO mode: alert (default empty)
      "attacksoundhi" : string, // alternate sounds for 3DO mode: attack (default empty)
      "painsoundhi"   : string, // alternate sounds for 3DO mode: pain (default empty)
      "deathsoundhi"  : string, // alternate sounds for 3DO mode: death (default empty)
      "activesoundhi" : string, // alternate sounds for 3DO mode: active (default empty)

      // Special behaviors - arrays of strings
      "flags"  : [ ... ], // Bit flags for special behaviors - default empty
      "flags2" : [ ... ], // More bit flags for special behaviors - default empty

      /*
         "flags" values:
         "special"      : Call TouchSpecialThing when touched
         "solid"        : Blocks movement
         "shootable"    : Can be hit by tracers
         "nosector"     : No sector links
         "noblockmap"   : No blockmap links
         "ambush"       : Cannot hear sound
         "justhit"      : Will try to attack right back
         "justattacked" : Will step before attack
         "spawnceiling" : Spawns hanging from ceiling instead of on floor
         "nogravity"    : Not subject to gravity
         "dropoff"      : Allows jumps from high places
         "pickup"       : Can pickup items
         "noclip"       : No clipping at all
         "slide"        : Slides against walls
         "float"        : Flying thing
         "teleport"     : Ancient beta movement hack
         "missile"      : Thing moves as a missile
         "dropped"      : Dropped by an enemy, not placed on map
         "translucent"  : Thing is translucent
         "countkill"    : Thing counts as a monster for certain purposes
         "corpse"       : Slides off steps
         "infloat"      : Floating to height for a move; don't autolevel
         "firedamage"   : Does fire damage
         "viewfacing"   : Billboard on both X and Z camera axes
         "skullfly"     : Moving like a lost soul
         "movie"        : Thing is involved in a movie
         "noinfighting" : Doesn't infight with other monsters ever
         "dontdraw"     : Don't draw sprite
         "blendadd"     : Render with additive blending
         "squashable"   : Player can stomp on this baddy
         "spawnrandomz" : Spawn at randomized z coordinate
         
         "flags2" values:
         "removeonactors"  : Remove missile if it hits an actor instead of exploding
         "hiresaddblend"   : Use additive blending if in hi-res actor mode
         "demodisabled"    : Actor is disabled for Guerrilla Games demo trailer
         "hashibloodtype"  : Actor uses hibloodtype when hi-res mode is enabled
         "door"            : Actor is a door
         "alwaysrespawn"   : Actor can always respawn
         "norespawn"       : Actor never respawns
         "norotations"     : Ignore sprite frame rotations even if provided in KPF/TARC
         "keepnogravity"   : Keep no gravity bit when dying
         "hireskeepnograv" : Ditto but only applies when enemy is hi-res
         "wokeup"          : Actor has been awake at least once
         "burned"          : Actor has been converted into cinders via dying in flames
      */
      
      // Blood types
      "bloodtype"   : string, // blood type (Default: "red")
      "hibloodtype" : string, // blood type for hi-res (Default: "red")
      
      /*
         blood type values:
         "red"
         "sparks"
         "green"
         "none"
      */

      // Lighting
      "lightr"       : byte,    // light red
      "lightg"       : byte,    // light green
      "lightb"       : byte,    // light blue
      "lightradius"  : integer, // light radius (default 0 - no light)
      "lightoffsetx" : integer, // light offset x
      "lightoffsety" : integer, // light offset y
      "lightoffsetz" : integer, // light offset z

      // Item drops
      "dropchance" : uint, // overall chance of an item dropping out of 255
      "droprolls"  : uint, // number of drop rolls (default 0)
      "drops" :            // definition of items to drop (default empty) - array of objects
      [
         {
            "item"   : string,  // Name of actor definition to spawn
            "chance" : integer, // chance out of 255 to select this item
            "isbad"  : boolean  // item is considered bad for the player
         },
         ...
      ],
      
      // Touch effect - controls item pickups
      "toucheffect" : { ... }, // Object of a specific touch effect type, see below.

      // 3DO actor behavior and rendering support
      "hires" :  // 3DO mode flags - array of strings (default empty)
      [
         ...
      ],
      /*
         "hires" values:
         "toggled"        : Sprite adds "3DO/" prefix to its resource name when hi-res mode is active
         "usealtstates"   : Actor uses alternate states when hi-res mode is active
         "noscaleoffsets" : If combined with one of the other values, the actor's sprite offsets are not scaled
         
         Note that "toggled" and "usealtstates" are strictly exclusive of each other.
         One behavior or the other must be selected, or neither. Actors with neither behavior 
         specified do not change when hi-res mode is toggled.
      */
      
      "hiresscale"   : float,   // hi-res scale factor (default 0.25)
      "scale"        : float,   // normal sprite scale (default 1.0)
      "hialpha"      : byte,    // if non-zero, alpha when hi-res only (default 0)
      "footoffset"   : integer, // offset to add to feet when low-res (default 0)
      "hifootoffset" : integer, // offset to add to feet when hi-res (default 0)

      // Infighting
      "noinfightwith" : string or string array, // List of monster names it will not infight with (default empty)
      "missilespecies" : string                 // Other actors that specify the same non-empty value cannot damage each other with missiles (default empty)
   }

The following global AngelScript functions exist to access ActorInfo (see 
scripting.txt for documentation):

   bool IsValidActorClass(uint classnum);
   const ActorInfo @ActorInfoForString(const kStr &in str);
   const ActorInfo @ActorInfoForNum(uint index);
   
--------------------------------------------------------------------------------
Touch Effects
--------------------------------------------------------------------------------

Each actor definition can contain a touch effect object which describes what
happens if a player touches the object while it has the ActorFlags::SPECIAL 
flag. This object can be of several distinct types, the type determining which
fields have meaningful values.

Pickup types include the following:
  * NONE       - placeholder, no effect
  * WEAPON     - Item gives the player a weapon
  * AMMO       - Item gives the player ammo
  * POWERUP    - Item gives the player a powerup effect
  * HEALTH     - Item gives the player a positive amount of health
  * DAMAGE     - Item deals damage to the player
  * KEY        - Item acts as a key (see also lockdefs)
  * TESSOBJECT - Item gives a Winged Vessel inventory item
  * SCRIPTED   - Item effect is determined via script callback
  
The touch effect value in an actor must be an object, and has the following schema:

  {
    "type" : string, // One of the values above
    
    // These fields are shared between all types:
    "sound"    : string, // Sound effect to play when successfully collected
    "tactile"  : string, // Tactile effect to invoke when successfully collected
    "message"  : string, // Message to display if collected; supports localization tokens
    "priority" : string, // Message priority level, as below:
    /*
      "Normal",  // White message, bottom-most row
      "Higher",  // Yellow message, middle row
      "Highest", // Purple message, top row
    */
    "useflash"   : boolean, // If true, causes an overlay flash when collected
    "flashtime"  : integer, // Flash duration in tics
    "flashcolor" : object or array, // Flash color, one of two formats:
    /*
      Object format:
      { "r" : byte, "g" : byte, "b" : byte, "a" : byte }
      
      Array format:
      [ byte, byte, byte, byte ] // Order is RGBA
    */
    
    // For type "WEAPON" : 
    "weapon"       : string,  // Name of weapon definition to give to the player
    "alwayspickup" : boolean, // If true, player picks up even if unneeded
    
    // For type "AMMO" :
    "ammo"       : string, // Name of ammo definition to give to the player
    "giveweapon" : string, // Name of a weapon to give along with the ammo, if non-empty
    "amounts"    : array or integer, // Amount of ammo to give. If array, ammo per skill level (0-5); if single integer, applies to all skills
    
    // For type "POWERUP" :
    "power" : string, // Name of powerup to give, as below:
    /*
      "invisible"    : Partial invisibility, movement speed is increased
      "showsecret"   : Secrets become visible on the automap 
      "maxhealth"    : Player maxhealth is permanently increased to megahealth value from player.json 
      "strength"     : Melee weapon damage is increased 
      "showmap"      : The entire map is revealed temporarily 
      "gotammo"      : Infinite ammo for weapons which allow it 
      "showmonsters" : Monster locations are temporarily shown on the automap
      "recharge"     : Add one charge for all Winged Vessels
      "godmode"      : Total invincibility
      "genocide"     : All shootable objects in a radius near the player are destroyed
      "showgoodies"  : Pickup items are temporarily visible on the automap
      "divinehealth" : Non-recoverable megahealth is given to the player
      "firefaster"   : Player weapons fire at a faster rate
      "halfdamage"   : Player temporarily takes half damage from all sources
      "nofiredamage" : Player is immune to damage from actors and inflictors flagged as FIREDAMAGE
      "light"        : All sectors are rendered at 255 light and fog is disabled
    */
    
    // For type "HEALTH" :
    "amount" : integer, // Amount to heal the player
    "maxout" : boolean, // If true, will not heal beyond player maxhealth
    
    // For type "DAMAGE" :
    "damage" : integer, // Amount of damage to inflict
    
    // For type "TESSOBJECT" :
    "tesseffect" : string, // Name of a Winged Vessel effect as below:
    /*
      "Invisible"
      "ShowSecrets"
      "MaxHealth"
      "Strength"
      "ShowMap"
      "GotAmmo"
      "ShowMonsters"
      "Recharge"
      "GodMode"
      "Genocide"
      "ShowGoodies"
    */
    
    // For type "SCRIPTED" :
    "function" : string, // Name of AngelScript function to invoke (see scripting.txt)
  }

--------------------------------------------------------------------------------
Animations - defs/animations.json
--------------------------------------------------------------------------------

Defines animated floor/ceiling/wall textures and switches. The global scope must 
contain a JSON object with two fields - "animations" and "switches". These are 
in turn arrays of objects. Both types of animation define the same fields but 
are treated differently when applied by the game engine.

The definitions should follow the following schema:

   {
      // Defines passive floor/ceiling/wall animations:
      "animations" : [
         {
            "name"    : string, // A unique name for this animation, for purposes of reference
            "texture" : string, // Texture name to which this animation applies, as used in maps (without any file extension)
            
            // Array of one or more step objects defining how the animation progresses:
            "steps" : [
               {
                  "delay"   : integer, // Number of 60 Hz tics this step lasts
                  "texture" : string   // Name of texture to display for this step
               },
               ...
            ]
         },
         ...
      ],
      
      // Defines animations which occur when a switch-type line action is activated:
      "switches" : [
         // same as animations, but a delay value of 0 means to last forever until the switch is toggled
      ]
   }

--------------------------------------------------------------------------------
Doors - defs/doordefs.json
--------------------------------------------------------------------------------

Defines swinging door models. Swinging doors can be placed in the map using the
SwingingDoor actor with editor number 10003. UDMF mapthing arg0 is the direction
to open (0 or 1) and UDMF arg1 is the ID of the door definition to use.

The file should be an array of zero or more objects with the following schema:

   [
      // Door def object:
      {
         "doornum"      : uint,   // ID of door def, should be unique
         "width"        : uint,   // Width in map units of "wide" sides of door
         "height"       : uint,   // Height in map units
         "depth"        : uint,   // Depth (jamb size) in map units; default 8
         "main_texture" : string, // Texture name to use for "wide" sides of door
         "jamb_texture" : string, // Texture name to use for jamb sides of door
         "main_offsetx" : float,  // X offset of main door sides (default 0)
         "main_offsety" : float,  // Y offset of main door sides (default 0)
         "jamb_offsetx" : float,  // X offset of jamb door sides (default 0)
         "jamb_offsety" : float,  // Y offset of jamb door sides (default 0)
         "main_uscale"  : float,  // Scale of main texture u texture coordinates (default 1.0)
         "main_vscale"  : float,  // Scale of main texture v texture coordinates (default 1.0)
         "jamb_uscale"  : float,  // Scale of jamb texture u texture coordinates (default 1.0)
         "jamb_vscale"  : float,  // Scale of jamb texture v texture coordinates (default 1.0)
         "opensound"    : string, // Path to sound to play when door is opened
         "movesound"    : string, // Path to sound to play as soon as opening sound finishes
         "flipmaintex"  : boolean // If true, flip the main texture left-to-right
      },
      ...
   ]
   
The following AngelScript functions exist for accessing DoorDef objects (see 
scripting.txt for documentation):

   uint GetNumDoorDefs();
   const DoorDef @GetDoorDefAt(uint idx);
   const DoorDef @DoorDefForDoorNum(uint doornum);

   const DoorDef @Actor::GetDoorDef() const;
   
--------------------------------------------------------------------------------
LockDefs - defs/lockdefs.json
--------------------------------------------------------------------------------

Defines keys for activation of locked line actions.

The file should be an array of objects with the following schema:

   [
      // Lockdef object:
      {
         "locknum"     : uint,    // Integer greater than 0, unique lock ID
         "needmessage" : string,  // String to give player as message if cannot open; supports localization tokens
         "nocheat"     : boolean, // If true, key will not be given by givekeys or giveall cheats unless forced with a "1" parameter
         "lockedsound" : string,  // If non-empty, sound to play when player cannot open this lock
         
         // A single predicate object, or an array of predicate objects, to determine
         // what keys are needed to open this lock:
         "predicates" : [
            // predicate object:
            {
               "type"  : string,          // "any" or "all", see below
               "actor" : string,          // A single actor name the player must possess as a key
               "actors" : [ string, ... ] // One or more actor names the player must possess as keys
            },
            ...
         ]
         /*
            Predicate type explanation:
            "any" - The player only has to possess one of the keys listed in this predicate
            "all" - The player must possess all keys listed in this predicate
            All predicates must be satisfied simultaneously for the lock to open
         */
      },
      ...
   ]

The following AngelScript functions are provided to interact with LockDefs (see
scripting.txt for documentation):

   uint GetNumLockDefs();
   const LockDef @GetLockDefAt(uint idx);
   const LockDef @LockDefForLockNum(uint locknum);
   bool P_CheckKey(Player @pPlayer, int keyNum, bool giveNeedMsg);

--------------------------------------------------------------------------------
MapInfo - defs/mapinfo.json
--------------------------------------------------------------------------------

MapInfo provides information on maps which cannot be specified within the maps 
themselves. The file should contain an object with keyed values which are each 
a MapInfo object, with the key matching the name of the map to which that object
applies.

{
   // "MAPxy" must be between MAP00 and MAP99 to work correctly with all engine features
   "MAPxy" : {
      "levelname"        : string,  // Name of level for automap; supports localization tokens
      "author"           : string,  // Name of level author; supports localization tokens
      "skytexture"       : string,  // Name of sky texture as used in map (no file extension)
      "soundpropagation" : boolean, // If true, full sound propagation behavior will be turned on
      "worldmap"         : string,  // If non-empty, name of graphic to use on automap's world map feature
      
      // RGBA fog color (vec4)
      "fogcolor"    : [ float, float, float, float ],
      "fogdistance" : float, // distance factor for fog 
      "fogpower"    : float, // power factor for fog
      
      "nextlevel"   : integer, // next level to visit when a normal exit line action is used with tag 0
      "nextsecret"  : integer  // next level to visit when a secret exit line action is used with tag 0
   },
   ...
}

A map without any MapInfo defined has the following defaults applied. The same 
defaults apply if any field in a MapInfo object is left unspecified:

   {
      "levelname"        : "$mapinfo_newlevel",
      "author"           : "$mapinfo_anonymous",
      "skytexture"       : "0",
      "soundpropagation" : false,
      "worldmap"         : ""
      "fogcolor"         : [ 0.0, 0.01, 0.02, 0.75 ],
      "fogdistance"      : 300,
      "fogpower"         : 2,
      "nextlevel"        : 0,
      "nextsecret"       : 0
   }
   
MapInfo can be interacted with from AngelScript using the following functions 
(see scripting.txt for documentation):

   const MapInfoDef @MapInfoForStr(const kStr &in name);
   const MapInfoDef @Game::GetMapInfo() const;

--------------------------------------------------------------------------------
Metrics - defs/metrics.json
--------------------------------------------------------------------------------

Defines basic gameplay metrics which were previously hard-coded values. This 
file can only contain a single object, which should follow this schema:

   {
      "stepheight"      : float,  // max height objects can step up/down ledges (default 24 units)
      "maxmove"         : float,  // max momentum of moving object (default 30 units/step)
      "floatspeed"      : float,  // speed monsters use when floating toward target (default 8 units/step)
      "gravity"         : float,  // normal gravity factor (default 4 units/tic^2)
      "stopspeed"       : float,  // speed below which player is considered standing still (default 0x1000 / 0x10000)
      "friction"        : float,  // factor to multiply momentum by for friction (default 0xd240 / 0x10000)
      "airfriction"     : float,  // air friction for players to enhance jumping (default 65520 / 65536)
      "damagethrust"    : float,  // factor to use when calculating damage thrust on target (default 25 units/tic)
      "meleerange"      : float,  // max distance for melee attacks (default 70 units)
      "shotrange"       : float,  // max distance for missile attacks (default 32 * 64 units)
      "basethreshold"   : int,    // threshold imparted on newly attacked monsters, time til changes target again (105 steps)
      "respawntics"     : int,    // minimum time before actor can respawn (1920 tics)
      "respawnprob"     : uint,   // probability per try out of 255 that actor will respawn (4)
      "gibsound"        : string, // Path to sound to play if actor is crushed by a moving sector
      "switch1sound"    : string, // Path to sound to play when a switch is triggered
      "switch2sound"    : string, // Path to sound to play when line special type 11 is triggered
      "fireactor"       : string, // Name of actor type to spawn on actors killed by objects with FIREDAMAGE flag
      "respawnfog"      : string, // Name of actor type to spawn at source and dest for respawning objects
      "respawnsound"    : string, // Path to sound to play for respawning actors
      "ceilingsound"    : string, // Path to sound to play for ceiling motion
      "dooropensound"   : string, // Path to sound to play for opening doors
      "doorclosesound"  : string, // Path to sound to play for closing doors
      "floorstartsound" : string, // Path to sound to play for starting a floor action
      "platmovesound"   : string, // Path to sound to play for moving plat actions
      "putvesselsound"  : string, // Path to sound to play when placing a Winged Vessel
      "allvesselsound"  : string  // Path to sound to play when all vessels have been placed
   }

The metrics object can be accessed in AngelScript as a global variable with the
following definition (see scripting.txt for documentation):

   MetricsDef g_metricsDef;

--------------------------------------------------------------------------------
Movies - defs/movies.json
--------------------------------------------------------------------------------

Defines properties of in-game ghost movies. The file should contain a single
object which has fields which are keyed by the path of each movie file. The
file should follow this schema:

   {
      "path/to/movie.webm" : {
         "xoffset"   : integer, // X offset
         "yoffset"   : integer, // Y offset
         "height"    : uint,    // Height at which to render movie in game world
         "blendmode" : string,  // One of the following blendmode values:
         /*
            blendmode values:
               "SOLID"          : no alpha blending
               "TRANSLUCENT"    : normal translucency
               "ADDITIVE"       : additive blending (saturating)
               "BLACKALPHA"     : 
               "ADDITIVESHADOW" : 
         */
         "opacity"   : float,   // Opacity for shadow only, 0.0 to 1.0
         "ytop"      : integer, // Y coord within movie data for top of displayed area 
         "ybottom"   : integer  // Y coord within movie data for bottom of displayed area
      },
      ...
   }

--------------------------------------------------------------------------------
Music - defs/music.json
--------------------------------------------------------------------------------

Actors placed in the world change the current music track for that sector, the 
track number is stored in arg0. This maps those IDs to a filename. Tracks may 
also have special tags to indicate to the game/engine they should be used for a 
specific purpose (menu and credits music).

The file should contain an array of objects which obey the following schema:

   [
      {
         "id"            : uint,   // Unique numeric ID for use in maps
         "filenameHires" : string, // Path to file with best quality (preferred)
         "filename"      : string, // Path to normal quality file
         "special"       : string  // Special music type (see below)
         /*
            special music types:
            "menu"    : used for menu screen
            "credits" : used for credits sequence
         */
      },
      ...
   ]

--------------------------------------------------------------------------------
Names - defs/names.json
--------------------------------------------------------------------------------

Defines special player names which can be entered at the beginning of a new game
to start with different loadouts.

File should be an array of zero or more objects with the following schema:

   [
      {
         "name"           : string,  // Unique name. Is matched case insensitive.
         "giveweapon"     : string,  // Name of weapon def to give the player
         "takeweapon"     : string,  // Name of weapon def to take from the player
         "giveammo"       : string,  // Name of ammo def to give to the player
         "giveammoamount" : integer, // Amount of ammo named by 'giveammo' to give the player
         "spawnhealth"    : integer, // Spawnhealth override for player, if not 0
         "maxhealth"      : integer, // Maxhealth override for player, if not 0
         "nopickups"      : boolean  // If true, player will not be able to collect special items
      },
      ...
   ]


--------------------------------------------------------------------------------
Player Def - defs/.json
--------------------------------------------------------------------------------

Defines static metrics related specifically to the player.

This file can only contain a single object with the following schema:

   {
      "maxhealth"        : integer, // Health when player is reborn (default 100)
      "megahealth"       : integer, // Health when enhanced (default 200)
      "viewheight"       : float,   // Viewheight (default 80 units)
      "deathviewheight"  : float,   // Viewheight when dead (default 8 units)
      "maxpitch"         : float,   // Max view pitch (default 90)
      "minpitch"         : float,   // Min view pitch (default -90)
      "maxbob"           : float,   // Max viewbob height (default 16 units)
      "jumpheight"       : float,   // Max jump height (default 16 units)
      "raisespeed"       : float,   // Weapon raising speed (default 8 units / tic)
      "lowerspeed"       : float,   // Weapon lowering speed (default 8 units / tic)
      "weaponbottom"     : float,   // Bottommost y for hiding weapon (default 200 units)
      "weapontop"        : float,   // Topmost y for showing weapon (default 32 units)
      "userange"         : float,   // Range for player use trace (default 64 units)
      "missileaimdist"   : float,   // Distance autoaim works over for missiles (default 16 * 64 units)
      "missilez"         : float,   // Default missile firing height (subtracted from z + height) (default 58 units)
      "reach"            : float,   // Reach for items (default -8 units)
      "screammomz"       : float,   // Momz threshold for screaming when falling into water death sector (default -6 units/tic)
      "clickdelay"       : integer, // Weapon click sound minimum frequency (default 25 tics)

      "invisibilitytics" : integer, // Invisibility powerup duration (default 3600 tics)
      "showsecretstics"  : integer, // Show secrets powerup duration (default 7200 tics)
      "strengthtics"     : integer, // Strength powerup duration (default 3600 tics)
      "gotammotics"      : integer, // "got ammo" powerup duration (default 1800 tics)
      "showmonstertics"  : integer, // "show monsters" powerup duration (default 7200 tics)
      "godmodetics"      : integer, // God mode powerup duration (default 1800 tics)
      "showgoodiestics"  : integer, // "show goodies" powerup duration (default 7200 tics)
      "firefastertics"   : integer, // Fire faster powerup duration (default 2700 tics)
      "halfdamagetics"   : integer, // Half damage powerup duration (default 2700 tics)
      "nofiredamagetics" : integer, // No fire damage powerup duration (default 3600 tics)
      "lighttics"        : integer, // Light amp powerup duration (default 5400 tics)

      "genocideradius"   : float,   // Distance for genocide powerup effect (default 1536 units)
      "genocidedamage"   : integer, // Damage to do in genocide effect (default 4000 HP)
      "genocidefog"      : string,  // Actor type to spawn for genocide effect

      "strengthweapon"   : string,  // Weapon name from weapons.json to change to when getting strength powerup 
      
      "jumplandsound"    : string,  // Jump-land sound effect name
      "splashsound"      : string,  // Landing in water sound effect name
      "splashexsound"    : string,  // Walking in water sfx
      "fallingsound"     : string,  // Scream when falling
      "tesseffectsound"  : string,  // Use tess effect sfx
      "powerdownsound"   : string,  // Power-up expire sfx
      "wrathsound"       : string,  // Wrath of gods effect sfx
      "nowaysound"       : string,  // Sound when pressing on useless walls
      
      "actorclass"       : string   // Name of actor type from actors.json to use as player's body (MUST be valid)
   }

The player def object can be accessed in AngelScript as a global variable with
the following definition (see scripting.txt for documentation):

   PlayerDef g_playerDef;

--------------------------------------------------------------------------------
Skyboxes - defs/skyboxes.json
--------------------------------------------------------------------------------

Defines 3D cubemap texture to use for enhanced sky rendering mode.

The file should contain a single object which has as its fields arrays which 
are keyed by the sky texture name (as used in maps, without a file extension).
Each array must contain exactly six texture names.

An example is provided:

   {
      "0" : [
         "cubemap_1_rt", "cubemap_1_lf", "cubemap_1_bk", "cubemap_1_ft", "cubemap_1_up", "cubemap_1_dn"
      ]
   }

Skyboxes can be looked up in AngelScript using the following function (see 
scripting.txt for documentation):
   
   const Skybox @SkyboxForString(const kStr &in texturename);

--------------------------------------------------------------------------------
Actor States - defs/states.json
--------------------------------------------------------------------------------

Defines animation and logic states for actors. 

Must be an array of ActorState objects. Each actor state must have a unique name.
The order of state objects is important; when using a nextstate value of "next",
the next state defined is the next state to which the actor will transition.

The first state must be named "Null" and is used to mark actors for removal from
the gamesim. This state should not be edited.

   [
      {
         "action"      : string,  // Name of an AngelScript function to invoke (see below)
         "fullbright"  : boolean, // If true, this frame is drawn at full brightness
         "sprite"      : string,  // Prefix for sprite graphics
         "frame"       : uint,    // Numeric value of sprite frame
         "tics"        : int,     // Duration of state. 0 is instantaneous; -1 lasts forever.
         "translucent" : boolean, // If true, frame is rendered with translucency
         "nextstate"   : string,  // Name of next state, or special value. See below.
         "altstate"    : string   // If actor/weapon uses alternate states for hi-res mode, the named state is used instead when jumps to this state occur
      },
      ...
   ]
   
On Actions:
   Actions are defined in the game's scripts as AngelScript functions. For
   actor actors, the AngelScript function must have the following signature:
   
      void ActionName(Actor @actor) { ... }
      
   For weapon actions, the AngelScript function must have the following signature:
   
      void ActionName(Player @player, pspdef_t @psp) { ... }
      
   If the function does not exist by name, or does not have the proper signature
   for the type of call being made to it, then nothing will happen. The name "Null"
   and the empty string value are both reserved to always mean nothing will happen.
   
Special nextstate values:
   The following special values are supported in the "nextstate" field:
      "next" : Go to the next state defined in states.json
      "prev" : Go the previous state defined in states.json
      "stop" or "null" : Go to state 0 (the "Null" state)
      "loop" : Stay in the same state, restarting the tics from scratch and invoking any action again
      "goto" : If "goto name", goes to that named state; if "goto name+integer" or "goto name-integer",
               goes to the state by relative enumeration within states.json.

The following AngelScript functions can be used to interact with states (see
scripting.txt for documentation):

   const ActorState @StateForString(const kStr &in str);
   const ActorState @StateForNum(uint index);
   const ActorState @Actor::GetState() const;

--------------------------------------------------------------------------------
Weapons and Ammunition - defs/weapons.json
--------------------------------------------------------------------------------

Defines ammunition and weapons.

The file must contain a global object, and allows two different fields: 
"ammotypes" and "weapons".

"ammotypes" must be an array of AmmoType objects, which have the following schema:

   {
      "ammotypes" : [
         // AmmoType object:
         {
            "name"      : string,  // Unique name for this ammo type; "None" is reserved.
            "maxammo"   : integer, // Maximum carrying capacity
            "startammo" : integer, // Amount a newly spawned player starts with
            "infinite"  : boolean  // If true, this type of ammo is inexhaustible and has no visible amount
         },
         ...
      ],
      ...
   }

"weapons" must be an array of WeaponDef objects, which have the following schema:
   
   {
      "weapons" : [
         {
            "name"         : string,   // Unique name for this weapon; "None" is reserved.
            "startwith"    : boolean,  // If true, is a default starting weapon for the player
            "melee"        : boolean,  // If true, is treated as a melee weapon (doesn't thrust)
            "stealth"      : boolean,  // If true, using it does not alert monsters (no sound)
            "priority"     : uint,     // Relative priority for automatic weapon selection
            "slot"         : uint,     // Slot number this weapon sits in, from 0 to 9
            "slotorder"    : uint,     // Order this weapon should occur in within its slot
            "ammo"         : string,   // Name of ammo type to use
            "pickupammo"   : uint,     // Amount of ammunition given when weapon is picked up
            "ammopershot"  : integer,  // Amount used when firing, and minimum needed to fire
            "upstate"      : string,   // Name of state to use for raising/selecting weapon
            "downstate"    : string,   // Name of state to use for putting away/changing weapon
            "readystate"   : string,   // Name of idle state
            "attackstate"  : string,   // Name of state for performing attack
            "flashstate"   : string,   // Name of underlaid firing animation (hi-res mode only)
            "shellstate"   : string,   // Name of first ejected shell animation (hi-res mode only)
            "shell2state"  : string,   // Name of second ejected shell animation (hi-res mode only)
            "clicksound"   : string,   // Name of sound effect to play if attempted to fire without ammo
            "clicksoundhi" : string,   // Ditto but for hi-res mode
            "upgrade"      : string,   // Name of a weapon to give if a second weapon of this type is collected
            "hiresscale"   : float,    // Scale of hi-res mode graphics (default 1.0)
            "usealtstates" : boolean,  // If true, use alternate states for hi-res mode
            "autotlate"    : boolean,  // If true, sprites append "3DO/" when in hi-res mode
            "automapicon"  : string,   // Graphic to draw on automap for this weapon
            "automapslot"  : integer,  // If not -1, slot to use on automap for this weapon (0 to 5; default -1)
            
            "allowInfiniteAmmo" : boolean  // If true, weapon respects infinite ammo powerup (default true) - only affects HUD and automap displays
         },
         ...
      ],
      ...
   }

Note: Keybinds for weapon slots on keys 8, 9, and 0 can be enabled by editing the 
"menu/options/input/bindings.rml" file - bind items are already provided in that
file and have been commented out with instructions on how to re-enable them
(*.rml is a HTML-like format and can be edited in any text editor). No weapons 
exist in these slots by default so the binds are not available normally to avoid
end-user confusion.
   
The following AngelScript functions can be used to interact with weapon 
definitions (see scripting.txt for documentation):

   const WeaponDef @WeaponDefForString(const kStr &in str);
   const WeaponDef @WeaponDefForIndex(uint idx);
   uint NumWeaponDefs();
  
   const WeaponDef @Player::GetReadyWeaponDef() const;
   const WeaponDef @Player::GetPendingWeaponDef() const;
   const WeaponDef @Player::FindNextWeapon() const;
   const WeaponDef @Player::FindPrevWeapon() const;

================================================================================
EOF
================================================================================
