1 Terms
=======
- excitement (float, [0, 1])
  character's excitement value, orgasm at 1

- tiredness (float, [0, 1])
  how tired a character is:
    - "base" tiredness starts at 0, goes up slightly for every orgasm,
      decays when excitement stays low enough
    - "actual" tiredness is never below base, but always shoots up to 1.0
      quickly after orgasm and slowly goes back to base

- energy (float, [0, 1])
  how energetic a character is, goes up with excitement but can be dampened
  by tiredness; see *TirednessFactor

  energy is used for gaze and movement, but with independent factors,
  because dampening movement too much makes the scene less interesting

- busy
  used for some gaze targets; whether a person is currently doing an action
  where they're unlikely to look away, such as a HJ, BJ, etc.

- gaze weight
  each gaze target has a weight as a number; to decide which target a
  person should look at next, the chance of a target being picked is its
  weight divided by the sum of the weight of all targets (that is, the
  higher the weight, the more chances a target has of getting picked)

  a weight of -1 makes that target exclusive

- personal space
  a character is inside another character's personal space when certain
  body parts are close enough (this is an expensive check, so only some
  body parts are handled, such as hands, head, chest, hips, genitals and
  feet)

- groped
  whether a character's head, breasts or genitals are currently being
  touched by another character

- sex
  includes both penetration and groping

- scene idle
  the current scene is considered idle if the excitement of all characters
  is 0

- gaze emergency
  something characters should be looking at immediately, such as another
  character orgasming or the player's eyes when grabbing the head


2 Types
=======
Various types used for the values in the JSON file.


2.1 Durations
-------------
These are configurable durations that can have their min/max change
depending on excitement.

A duration can be a simple array with two floats: the minimum and maximum in
seconds. The duration is a random number generated between the min and max,
regenerated every time the duration elapses.

A duration can also have a sliding window, which is a smaller window within
the min and max that moves towards the max as excitement goes up.

For these sliding durations, the duration is an object with two subobjects:
"range" and "nextTimeRange". Both are Range objects, described below. The
"range" object is for the duration itself, the "nextTimeRange" object is for
the interval after which the current range is regenerated.

A Range object has these values:

    min, max      minimum and maximum durations (seconds, required)

    window        duration range from the minimum, slides towards max as
                  excitement goes up (optional, seconds, defaults to full
                  range)

    windowEasing  the easing used for the sliding window (optional, default
                  "linear", see Enums/Easings.cs)

    rng           random generation algorithm (optional, defaults to
                  "uniform"); see RNG (2.2) below

As an example, a sliding duration with a min/max of [1.0, 2.0] and a window
of 0.2 would generate durations between [1.0, 1.2] if excitement is 0.0 and
between [1.8, 2.0] if excitement is 1.0. The json would be like this:

    "someDuration":
    {
        "range":
        {
            "min": 1.0,
            "max": 2.0,
            "window": 0.2
        }
    }


2.2 Random number generator (RNG)
---------------------------------
An RNG is an object used to generate random numbers. It can either be "uniform"
(each number in the range has an equal chance of being picked) or "normal" (the
chances of generating numbers is a on a curve).

RNGs of type "normal" are affected by the character's excitement.

An RNG can be a string "uniform" or "normal". It can also be an object with a
'type' value with the same strings. If the 'type' is "normal", these additional
values are supported:

    centerMin,   range of the center of the distribution, both [0, 1],
    centerMax    defaults to 0.5 for both; as excitement goes up, the center
                 goes towards the max

                 (this is used for the mean, as `(min + max) * center)`)

    widthMin,    range of the width of the distribution; as excitement goes,
    widthMax     up, the width goes towards the max

                 values above 1.0 make a flatter curve, values below 1.0 make
                 a higher peak around the center, defaults to 1.0 for both

                 (this is used for the sigma, as `3.0/width`)

Both ranges can be specified as simply "center" and "width" if the min and max
are the same.

For example, a simple uniform RNG:

    "rng": "normal"

A normal RNG:

    "rng":
    {
        "type": "normal",
        "centerMin": 0,
        "centerMax": 0.8,
        "width": 3
    }


3 Values
========

3.1 Gaze
--------
Controls what characters are looking at.

- GazeDuration (duration)
  time it takes to move the head to follow the eyes

- GazeRandomInterval (duration)
  time to wait before picking the next target

- EmergencyGazeDuration (duration)
  time it takes to move the head when looking at an emergency


- GazeSaccade (bool)
  whether saccades are enabled

- GazeSaccadeInterval (duration)
  time between saccades

- GazeSaccadeMovementRange (float)
  saccade movement range; a random value between [-this, +this] is picked for
  both horizontal and vertical offsets

- GazeBlink (bool)
  whether blinking is enabled

- GazeEyeTargetMovementSpeed (float)
  speed at which the eyeTargetControl moves between targets (in units per
  second)


3.2 Gaze avoidance
------------------

- AvoidGazePlayer (float)
  excitement value below which the character avoids looking at the player

- AvoidGazePlayerInsidePersonalSpace (float)
  excitement value below which the character avoids looking at the player when
  inside personal space

- AvoidGazePlayerDuringSex (float)
  excitement value below which the character avoids looking at the player
  when involved in sex

- AvoidGazePlayerDelayAfterOrgasm (float)
  time after orgasm during which avoidance with player is disabled, starts
  after the post-orgasm state (seconds)

- AvoidGazePlayerWeight (float)
  when the player is being avoided, weight of the player's eyes for gaze; set
  to -1 to actively avoid the player by picking a different target if the
  player gets into view

  see also AvoidGazeAnger

- AvoidGazeOthers (float)
  excitement value below which the character avoids looking at other characters

- AvoidGazeOthersInsidePersonalSpace (float)
  excitement value below which the character avoids looking at other
  characters when they're inside personal space

- AvoidGazeOthersDuringSex (float)
  excitement value below which the character avoids looking at other characters
  when involved in sex with this one

- AvoidGazeOthersDelayAfterOrgasm (float)
  time after orgasm during which avoidable with others is disabled, starts
  after the post-orgasm state (seconds)

- AvoidGazeOthersWeight (float)
  when other characters are being avoided, weight of the characters' eyes for
  gaze; set to -1 to actively avoid other characters by picking a different
  target if they get into view

  see also AvoidGazeAnger

- AvoidGazeUninvolvedHavingSex (float)
  excitement value below which this character avoids looking at other
  characters having sex with someone else


3.3 Gaze weights
----------------

- LookAboveMaxWeight (float)
  looking at a target directly above the character's head when mood is normal
  or post-orgasm; this weight is multiplied by the character's energy (see
  also LookAboveUseGazeEnergy)

- LookAboveMaxWeightOrgasm (float)
  looking at a target directly above the character's head during orgasm; this
  weight is multiplied by the character's energy (see also
  LookAboveUseGazeEnergy)

- LookAboveMinExcitement (float)
  excitement value below which looking up is disabled; avoids looking up for
  low excitement, since it's a pretty strong emote, should probably be higher
  than MaxOtherSexExcitement

- LookAboveMinPhysicalRate (float)
  physical rate value below which looking up is disabled; avoids looking up
  when the excitement source is only emotional (note that rates are low values,
  typically below 0.02)

- LookAboveUseGazeEnergy (bool)
  whether the weight is multiplied by the gaze energy, so that tired characters
  have less of a chance to look above; some personalities (like sleeping) may
  want to look above regardless of energy

- LookFrontWeight (float)
  looking at a point directly in front of the head

- IdleNaturalRandomWeight (float)
  looking at a random point when not busy and scene is idle

- IdleEmptyRandomWeight (float)
  looking at a random point when not busy and scene is idle, and there is only
  this character and the player in the scene

- NaturalRandomWeight (float)
  looking at a random point when not busy and scene is not idle

- NaturalOtherEyesWeight (float)
  looking at a random person when not busy; see also OtherEyesExcitementWeight

- BusyOtherEyesWeight (float)
  looking at a random person when busy; see also OtherEyesExcitementWeight

- NaturalPlayerEyesWeight (float)
  looking at the player randomly when not busy, used instead of
  NaturalOtherEyesWeight for the player (allows for randomly looking at the
  player more often)

- BusyPlayerEyesWeight (float)
  looking at the player randomly when busy, used instead of BusyOtherEyesWeight
  for the player (allows for randomly looking at the player more often)

- MaxTirednessForRandomGaze (float)
  tiredness value above which random points and targets are disabled [0, 1]

- OtherEyesExcitementWeight (float)
  used with naturalOtherEyesWeight and busyOtherEyesWeight: multiplied by the
  target's excitement and added to those weights; this is used to increase the
  chances of looking at a target that has a high excitement value

- OtherEyesOrgasmWeight (float)
  looking at a person who is currently orgasming


- BlowjobEyesWeight, BlowjobGenitalsWeight (float)
  if this character is giving a BJ, looking at the other character's eyes
  or genitals

- HandjobEyesWeight, HandjobGenitalsWeight (float)
  if this character is giving a HJ, looking at the other character's eyes or
  genitals

- PenetratedEyesWeight, PenetratedGenitalsWeight (float)
  if this character is being penetrated, looking at the other character's eyes
  or genitals

- PenetratingEyesWeight, PenetratingGenitalsWeight (float)
  if this character penetrating another, looking at the other character's eyes
  or genitals

- GropedEyesWeight, GropedTargetWeight (float)
  while being groped, looking at the other character's eyes or the body part
  being groped

- GropingEyesWeight, GropingTargetWeight (float)
  while groping another, looking at the other character's eyes or the body part
  being groped

- OtherBlowjobEyesWeight, OtherBlowjobTargetEyesWeight,
  OtherBlowjobTargetGenitalsWeight (float)
  if another character is giving a BJ, looking at that character's eyes or the
  target's eyes or genitals

- OtherHandjobEyesWeight, OtherHandjobTargetEyesWeight,
  OtherHandjobTargetGenitalsWeight (float)
  if another character is giving a HJ, looking at that character's eyes or the
  target's eyes or genitals

- OtherPenetrationEyesWeight, OtherPenetrationSourceEyesWeight,
  OtherPenetrationSourceGenitalsWeight (float)
  if another character is being penetrated, looking at that character's eyes or
  the penetrator's eyes genitals

- OtherGropedEyesWeight, OtherGropedSourceEyesWeight,
  OtherGropedTargetWeight (float)
  if another character is being groped, looking at that character's eyes or
  body part, or the groper's eyes


- LookAtPlayerOnGrabWeight (float)
  if the character's head is being grabbed by the player, looking at the player

- LookAtPlayerTimeAfterGrab (float)
  minimum time to keep looking at the player after the head grab has been
  released; the actual time might be longer since there might be a delay
  before the next target is picked



3.4 Excitement
--------------

- KissSpeedEnergyFactor (float)
  effect of energy on kiss movements; depends on the integration plugin, a
  value of 1.0 should make morph movements faster as energy goes up

- IdleMaxExcitement (float)
  excitement value under which the character is considered idle; when all
  characters in a scene are idle, some behaviours will change, such as looking
  around randomly

- TirednessExcitementRateFactor (float)
  impact of tiredness on excitement rate; slows down excitement buildup as
  tiredness goes up, that is, increases the delay between orgasms the more
  orgasms the character has in a row

  higher values give slower rates: 0.0 ignores tiredness and 1.0 will freeze
  the rate completely when tiredness is maxed out

  excitement rate is `rate - (rate * tiredness * this)`, where `rate` is the
  sum of emotional and physical rates and tiredness is [0, 1]

  example: if the rate is at 2.0, this is 0.6, and tiredness is maxed out at
  1.0, the excitement rate becomes `2.0 - (2.0 * 1.0 * 0.6)`, which is 0.8
  (go up at 40% speed when tiredness is maxed); if the tiredness is 0.5, the
  rate becomes `2.0 - (2.0 * 0.5 * 0.6)`, which is `1.4` (go up at 70% speed
  when tiredness is at half)

- GazeEnergyTirednessFactor (float)
  impact of tiredness on excitement to determine gaze energy; affects speed
  of head movement and delay between switching targets

  gaze energy is `excitement - (tiredness * this)`, clamped [0, 1]

- GazeTirednessFactor (float)
  impact of tiredness on gaze; inhibits some gaze targets, see
  MaxTirednessForRandomGaze

  gaze tiredness is `tiredness * this`, clamped [0, 1]

- MovementEnergyTirednessFactor (float)
  impact of tiredness on excitement to determine movement energy; affects
  the speed of various movements, such as sex animations

  movement energy is `excitement - (tiredness * this)`, clamped [0, 1]

- ExpressionTirednessFactor (float)
  impact of tiredness on expressions; affects range of morph values and rate
  of change for tired expressions, and dampens the other expressions

  expression tiredness is `tiredness * this`, clamped [0, 1]


- MovementEnergyRampUpDelayAfterOrgasm (float)
  time in seconds after orgasm after which energy ramp up starts; after this
  delay has elapsed, energy becomes 0 and will ramp up over time based on
  MovementEnergyRampUpAfterOrgasm

  this allows for animations to continue for a short period while the orgasm
  animation is playing

- MovementEnergyRampUpAfterOrgasm (float)
  time in seconds after post-orgasm until movement energy can be at its
  maximum again; if greater than 0, movement energy will be forced to 0 after
  post-orgasm and ramp up over time, which makes animations restart smoothly
  instead of being very fast right after orgasm

- MovementEnergyRampUpAfterOrgasmEasing (easing)
  easing used when ramping up movement energy


- ExcitementDecayRate (float)
  rate at which excitement decreases when there is no stimulation of any
  body part

- ExcitementPostOrgasm (float)
  excitement will reset to this value after orgasm

- OrgasmTime, PostOrgasmTime (float)
  time during which orgasms and post-orgasm states will last; both are used
  for animations and adjusting tiredness

- RateAdjustment (float)
  a flat value that multiplies the excitement rate, defaults to 1.0; this
  can be changed to globally increase or decrease the rate at which
  excitement changes

- PenetrationDamper (float)
  a flat value that multiplies the excitement rate of all sensitivities except
  penetration, only used while this character is being penetrated or is
  penetrating another

  this is used to increase the time between orgasm during sex regardless of
  interactions while still allowing quicker orgasms for more ad hoc interactions


- OrgasmSyncMinExcitement (float)
  syncs orgasms across characters; if any character in the scene is having an
  orgasm and this character's excitement is above this value, its orgasm will be
  triggered

- MinCollisionMag (float)
- MinCollisionMagPenetration (float)
  if the relative velocity of the collision between two body parts is lower than
  this, excitement won't rise; collisions between genitals is controlled by
  MinCollisionMagPenetration, all others are controlled by MinCollisionMag


3.5 Mood
--------

- DefaultHappiness (float)
  happiness mood will usually be set to this value

- DefaultPlayfulness (float)
  playful mood will usually be set to this value

- DefaultAnger (float)
  angry mood will usually be set to this value

- MaxHappyExpression (float)
- MaxExcitedExpression (float)
- MaxPlayfulExpression (float)
- MaxAngryExpression (float)
- MaxTiredExpression (float)
  the given expression intensity will never rise above this value


3.5.1 Anger management
----------------------

- AvoidGazeAnger (float)
  anger value when the character is currently looking at something it doesn't
  like; see AvoidGazePlayerWeight and AvoidGazeOthersWeight

- AngerWhenPlayerInteracts (float)
  anger value when the player is interacting with this character; as soon as
  interaction starts, anger is set to this value and happiness to 0

  if this is 0, none of the stuff below applies

- AngerMaxExcitementForAnger (float)
  excitement value above which this character starts being less angry; while
  excitement is below this, anger is always at AngerWhenPlayerInteracts

- AngerMaxExcitementForHappiness (float)
  excitement value above which this character starts getting happier; while
  excitement is below this, happiness is always at 0

- AngerExcitementFactorForAnger (float)
  impact of excitement on anger above AngerMaxExcitementForAnger

  anger is always at max when excitement is below AngerMaxExcitementForAnger,
  this determines how fast anger drops as excitement keeps rising

  for example:
  - a value of 1.0 would make anger drop to zero when excitement is at max
  - a value of 2.0 would make anger drop to zero when excitement is halfway
    between AngerMaxExcitementForAnger and max

- AngerExcitementFactorForHappiness (float)
  impact of excitement on happiness above AngerMaxExcitementForHappiness

  happiness is always at zero when excitement is below
  AngerMaxExcitementForHappiness, this determines how fast happiness rises with
  excitement

  for example:
  - a value of 1.0 would set happiness to max when excitement is at max
  - a value of 2.0 would set happiness to max when excitement is halfway
    between AngerMaxExcitementForHappiness and max


3.6 Voices
----------
Controls voices and breathing. The `provider` key can be either "macgruber" or
"vammoan". Provider-specific options are within an `options` object.

There are several different voice states, only one can be active at a time. Some
can be configured.


3.6.1 Normal state
Breathes or moans based on excitement.

- breathingRange (float)
  when excitement is below this value, only breathing is used

- breathingIntensityCutoff (float)
  when excitement is above this value, breathing is never used

- intensityWait (rng)
  the range of random numbers used to generate an interval to wait for before
  picking a new intensity

- intensityTarget (rng)
  a generator for the voice intensity, based on the character's excitement; this
  is a normal rng by default, so that the chances of generating a low intensity
  voice gets lower the higher the excitement rises

- intensityTime (rng)
  when a new intensity target is picked, time of the transition from the old
  intensity to the new one


3.6.2 Kiss state
Handles voice while kissing is active.

- enabled (bool)
  whether the voice should be adjusted during this state

- voiceTime (float)
  time after which a random moan is possible and also time during which moaning
  is active (seconds)

- voiceChance (float)
  chance of doing a random moan


3.6.3 Orgasm state
Handles voice during orgasm.

- voice (string)
  name of the orgasm state in VAMMoan


3.6.4 BJ state
Handles voice during BJ. Same as 3.6.3.


3.6.5 Choked state
Handles voice while the neck is grabbed.

- minTimeForMoaning (float)
  minimum time the choke must be active to moan once it's released (seconds)

- moaningAfter (float)
  moaning value once the choke is released [0, 1]

- moaningTime (float)
  time during which the moaning value is held

- rampDownTime (float)
  time during which moaning goes back to breathing


3.6.1 MacGruber

Controls the dataset used depending on excitement.

`datasets` array of objects, each object has:
   dataset:       name of the breathe dataset

   intensityMin,
   intensityMax:  range of intensities where this dataset is used; intensity
                  is [0, 1] and corresponds to the movement energy (see
                  MovementEnergyTirednessFactor)

`orgasm` object:
  dataset:        name of the orgasm dataset; if an empty string, disables
                  voice during orgasm


3.6.2 VAMMoan

Controls options for VAMMoan.


- orgasmAction
  the name of the action to trigger during orgasm



3.7 Appearance
---------------
Body temperature is defined by two numbers: the current value and the
target value, both [0, 1]. `temperatureExcitementMax` is used to determine the
target value based on excitement, and `temperatureExcitementRate` and
`temperatureDecayRate` are rates at which the current value increases or
decreases to reach the target

Skin flush is based on body temperature and air. When breathing stops by
grabbing the neck, air goes down towards 0 (see 3.8). `MaxFlush` and
`MaxChokedFlush` are used to determine the amount of red added to the skin
colour.

- FlushRedMag (float)
  maximum distance to lerp between the base skin colour and full red; MaxFlush
  and MaxChokedFlush multiply this

- MaxSweat (float)
  maximum gloss factor; 1.0 should be realistic, but can go above or below

- MaxFlush (float)
  max flush magnitude for body temperature

- MaxChokedFlush (float)
  max flush magnitude for choking

- TemperatureExcitementMax (float)
  the excitement value at which body temperature should be at 1.0 (its
  maximum); the target temperature is therefore
      `excitement / temperatureExcitementMax`, clamped[0, 1]

- TemperatureExcitementRate (float)
  the rate at which body temperature increases towards the current target based
  on the current excitement; the rate is the current excitement (values [0, 1])
  multiplied by this

- TemperatureDecayRate (float)
  rate at which the temperature decreases when the target is below the current
  temperature


3.8 Choking
-----------
When the neck is grabbed, breathing stops and air goes down from 1.0 towards 0.0
over time. Air goes back up when the neck is released. Air affects body colour
(see 3.7) and choking affects mood and voice.


- ChokedAirDownTime (float)
  when choking is active, time until air is 0 (seconds)

- ChokedAirUpTime (float)
  when choking stops, time until air is back to 1 (seconds)

- MinHappyChoked (float)
  MaxHappyChoked (float)
  MinPlayfulChoked (float)
  MaxPlayfulChoked (float)
  MinExcitedChoked (float)
  MaxExcitedChoked (float)
  MinAngryChoked (float)
  MaxAngryChoked (float)
  MinSurprisedChoked (float)
  MaxSurprisedChoked (float)
  MinTiredChoked (float)
  MaxTiredChoked (float)
  when choking becomes active, all moods are forced between these values, which
  can be used for temporary expressions (like surprised)



3.9 Tiredness
-------------
Tiredness is defined by two numbers: the base value and the current value,
both [0, 1]. The base tiredness starts at 0, goes up slightly for every
orgasm, and decays when excitement stays low enough. The current value is
never below base, but always shoots up to 1.0 quickly after orgasm and slowly
goes back to base.

- TirednessRateDuringPostOrgasm (float)
  the rate at which tiredness increases during the post-orgasm state; by
  default, the rate is high so 1.0 is reached during `postOrgasmTime`

- TirednessBaseDecayRate (float)
  the rate at which the base value decreases if excitement is lower than
  `tirednessMaxExcitementForBaseDecay`

- TirednessBackToBaseRate (float)
  the rate at which the current value decreases back to the base value

- DelayAfterOrgasmUntilTirednessDecay (float)
  time after post-orgasm during which the base value will not decay

- TirednessMaxExcitementForBaseDecay (float)
  if the excitement is above this, the base value will not decay

- OrgasmBaseTirednessIncrease (float)
  added to the base value on each orgasm

- MinTiredness (float)
  tiredness will never go below this value; useful for the sleeping personality


3.10 Sensitivity
----------------
Controls the rate at which excitement goes up when various body parts are
stimulated or events are happening. Each sensitivity has rates and maximum
values, some both for physical and non-physical body parts.

The nonPhysicalRate and nonPhysicalMax values are only used if the only body
part involved is a strapon.


- rate, or physicalRate and nonPhysicalRate
  the rate at which excitement goes up when this sensitivity is active

- max, or physicalMax and nonPhysicalMax
  the maximum excitement value that can be reached with this source alone; if
  this is not 1.0, the character cannot have an orgasm from this source

  if the excitement is above the max, this sensitivity is ignored


A sensitivity can also have a "modifiers" section, to adjust rates depending
on the source. The rate is multiplied by the modifier. The source can be "self",
"player" or an atom ID. If empty, the modifier applies to any source, which is
not very useful.

This feature is used to increase the rates when the player is touching
genitals, because the player is awesome, and to reduce rates for masturbation

The "othersExcitement" sensitivity is used to increase excitement if other
characters in the scene are currently being stimulated. Cue looks for the
character whose excitement is currently rising the fastest and multiplies their
excitement rate by this `rate` value.


3.11 Expressions
----------------
Defines a series of morphs or morph groups that are used randomly to animate
the character's face. Each expression is associated with a mood. The intensity
of the mood decides the value at which the morph is driven.

- name
  name of the expression, for display

- moods
  list of space-separated mood names for which this expression can be used;
  see Enums/Moods.cs

- bodyParts
  list of space-separated body part names (see Enums/BodyPartsEnum.cs) that are
  affected by this expression

  multiple expressions can be active at the same time, with random values, to
  create a variety of facial animations; if multiple expressions affect the same
  body part (such as the mouth), the face can become distorted because of
  compounding morphs

  Cue uses these body parts to limit the value of morphs when multiple
  expressions are active concurrently, making sure the total of all morph values
  affecting a body part doesn't exceed a certain maximum (currently around 1.1)

- morphs
  an array of morphs that are used in this expression, with an optional maximum
  value; this is a ghetto version of Vam's morph groups


3.12 Finish
-----------
These control the character's action when finishing. The term "involved"
currently means that the character is penetrating the player, or vice versa.


- FinishLookAtPlayer (string)
  determines whether the action in `FinishLookAtPlayerAction` is executed; can
  be "always", "involved" or "never"

    - always:   action is always executed
    - involved: action is executed only if involved
    - never:    action is never executed

- FinishLookAtPlayerAction (string)
  if `FinishLookAtPlayer` is true, this action will be executed; can be "look",
  "avoid" or "gaze"

    - look:  the character will look at the player
    - avoid: the character will look away from the player
    - gaze:  the character uses `AvoidGazePlayerDuringSex` to determine whether
             to look at or avoid the player

- FinishOrgasm (string)
  whether the character orgasms; can be "always", "involved" or "never"

    - always:   the character will always orgasm
    - involved: the character will orgasm only if involved
    - never:    the character will never orgasm

- FinishOrgasmMinExcitement (float)
  affects `FinishOrgasm`, the character will orgasm only if excitement is
  above this value

- FinishMood (string)
  can set the various moods to a specific value while finishing; can be
  "always", "involved" or "never"

    - always:   the moods are always set
    - involved: the moods are set only if involved
    - never:    the moods are never set

- FinishMoodHappy (float),
- FinishMoodPlayful (float)
- FinishMoodAngry (float)
- FinishMoodTired (float)
  sets the corresponding mood to the given value; use -1 to leave the mood
  unchanged


3.13 Events
-----------
Cue uses events for various things, like thrust or hands, but also reacting
to zaps, kissing, grabbing, etc. Some events are configurable.


3.13.1 Kiss
-----------
- startLipsDistance (float)
  distance between the lips of two characters (not including the player) below
  which kissing activates

- startLipsDistanceWithPlayer (float)
  distance between the lips of the player and other characters below which
  kissing activates

- stopLipsDistance (float)
  distance between the lips of two characters that are currently kissing (not
  including the player) above which kissing stops

- stopLipsDistanceWithPlayer (float)
  distance between the lips of the player and the other character that is
  currently kissing above which kissing stops

- stopHeadDistanceFromStart (float)
  distance from the initial head position when kissing started above which
  kissing stops; only with player

- duration (duration)
  time of the kissing event; note that kissing never stops if the player is
  involved

- interval (duration)
  cooldown period during which kissing cannot start again for this character


3.13.2 Hold breath
------------------
Pauses breathing randomly.

- minExcitement (float)
  excitement above which pauses are enabled

- cooldown (float)
  minimum time before the next pause (seconds)

- holdTime (duration)
  time during which the character doesn't breathe

- chance (float)
  changeRng (rng)
  every time the cooldown elapses, a random number is generated with changeRng;
  if it's below `chance`, the event activates


3.14 Zap
--------
When breasts, genitals or mouth are being touched, or when penetration is
active, a character can get "zapped". This happens when the zone hasn't been
active for at least `zappedCooldown` seconds. Zapping temporarily increases
excitement to a higher value to get expressions and can trigger gazes.


- zappedEnabled (bool)
  whether zapping is enabled

- zappedTentativeTime (float)
  minimum time that the zone has to be active before zapping, prevents
  zapping when the zone is just momentarily touched (seconds); note that a
  higher value reduces the number of false positives, but increases the reaction
  time

- zappedCooldown (float)
  minimum time before a zap can happen again, regardless of the zone (seconds)

- zappedTime (float)
  when zapping starts, the excitement value is immediately set to a higher
  value and will go down towards the base excitement over `zappedTime` seconds

- zappedGazeMinIntensity (float)
  minimum zap intensity to trigger gaze events

- zappedByPlayerBreastsEyesWeight (float)
  zappedByPlayerGenitalsEyesWeight (float)
  zappedByPlayerPenetrationEyesWeight (float)
  zappedByPlayerMouthEyesWeight (float)
  zappedByPlayerLookUpWeight (float)
  weight for looking at the eyes of the character that triggered the zap when
  that character is the player

- zappedByOtherBreastsEyesWeight (float)
  zappedByOtherGenitalsEyesWeight (float)
  zappedByOtherPenetrationEyesWeight (float)
  zappedByOtherMouthEyesWeight (float)
  zappedByOtherLookUpWeight (float)
  weight for looking at the eyes of the character that triggered the zap when
  that character is not the player

- zappedByPlayerBreastsTargetWeight (float)
  zappedByPlayerGenitalsTargetWeight (float)
  zappedByPlayerPenetrationTargetWeight (float)
  weight for looking at the zone that triggered the zap when the source is the
  player

- zappedByOtherBreastsTargetWeight (float)
  zappedByOtherGenitalsTargetWeight (float)
  zappedByOtherPenetrationTargetWeight (float)
  weight for looking at the zone that triggered the zap when the source is not
  the player

- zappedByPlayerBreastsExcitement (float)
  zappedByPlayerGenitalsExcitement (float)
  zappedByPlayerPenetrationExcitement (float)
  zappedByPlayerMouthExcitement (float)
  when the given zone is zapped by the player, excitement will be immediately
  set to the given value

- zappedByOtherBreastsExcitement (float)
  zappedByOtherGenitalsExcitement (float)
  zappedByOtherPenetrationExcitement (float)
  zappedByOtherMouthExcitement (float)
  when the given zone is zapped by a character that is not the player,
  excitement will be immediately set to the given value

- zappedByPlayerGazeDuration (duration)
  when the zap was triggered by the player, time it takes to move the head to
  look at whatever is being looked at; allows for quick head snap for zapping

- zappedByOtherGazeDuration (duration)
  when the zap was not triggered by the player, time it takes to move the head
  to look at whatever is being looked at; allows for quick head snap for zapping

- otherZappedEyesWeight (float)
  otherZappedTargetWeight (float)
  otherZappedSourceWeight (float)
  when another character is being zapped, weight for looking at their eyes,
  the zone being zapped or the eyes of the source of the zap

- otherZappedGazeDuration (duration)
  when another character is being zapped, time it takes to move the head
  to look at whatever is being looked at


3.15 Miscellaneous
-------------------

- IdleAnimation (string)
  the name of the idle animation to use


4 Inheritance
=============
Most of the default values are applicable to any personality. To avoid copying
all the values for new personalities, inheritance can be used instead.

If an "inherit" value is found, all the values from that personality are copied
first, then overridden by any new value in this new personality.

The special "abstract" field can be set to `true` to avoid showing it in the
personality list in the user interface. This is used in the "base" personality.
