Facial Expression System
Create dynamic facial animations that react to penetration depth, scene context, and actor size using simple TOML configuration files.
Overview
The facial expression system lets you define presets — sets of rules that control an actor's facial morphs during a scene. Each preset targets a specific orifice (mouth, vagina, anus, or hands) and contains one or more effects that adjust facial morphs like mouth shape, eyebrow position, or custom MFEE expressions.
Presets can respond to penetration depth, so expressions intensify the deeper the penetration goes. They can also be filtered by scene context (like aggressive or loving scenes) and penis size/girth for more nuanced control.
Setup
Facial presets are defined in TOML config files. You can place them in the main accurate-penetration.toml config file, or in override config files inside the ppa-override-configs folder.
If facial expressions aren't applying, try installing MFG Fix NG. If they still don't work, another mod is likely overwriting the expressions.
The expression system can be toggled on/off with EnableExpressionSystem in the [General] section of your config.
Basic Structure
Each preset starts with a [[FacialPreset]] header, followed by its properties. Effects are defined as sub-tables using [[FacialPreset.Effects]]. You can define as many effects per preset as you want.
# A simple preset that targets the mouth [[FacialPreset]] Targets = ["Mouth"] Priority = 10 Smoothing = 8.0 OverridePhonemes = true # First effect: open the mouth using phoneme 1 (BigAah) [[FacialPreset.Effects]] Type = "Phoneme" Index = 1 TargetValue = 0.8 # Second effect: add squinting using modifier 12 [[FacialPreset.Effects]] Type = "Modifier" Index = 12 TargetValue = 0.5
Multiple presets can target the same orifice. When that happens, the system picks the best match based on conditions and priority — more on that in How Presets Are Selected.
Preset Properties
These are the properties you set directly under a [[FacialPreset]] header.
| Property | Type | Description |
|---|---|---|
| Targets | string[] | Required Which orifice(s) activate this preset. Values: "Mouth", "Vagina", "Anus", "Hands". |
| Priority | integer | When multiple presets match, the highest priority wins. Default: 0. |
| Smoothing | float | How quickly the face transitions to target values. Higher = faster/snappier, lower = more gradual. Default: 8.0. |
| Contexts | string[] | Only activate when the scene matches these context flags. See Scene Contexts. If omitted, the preset matches any scene. |
| OverridePhonemes | bool | Zero out all phoneme morphs not set by this preset. Prevents conflicts with other mods controlling mouth shapes. Default: false. |
| OverrideExpressions | bool | Zero out all expression morphs not set by this preset. Default: false. |
| OverrideModifiers | bool | Zero out all modifier morphs not set by this preset. Default: false. |
| PenisSizeMin | float | Only match when the penetrating penis size is at least this value. Default: 0 (no minimum). |
| PenisSizeMax | float | Only match when the penetrating penis size is at most this value. Default: 0 (no maximum). |
| PenisGirthMin | float | Only match when the penetrating penis girth is at least this value. Default: 0 (no minimum). |
| PenisGirthMax | float | Only match when the penetrating penis girth is at most this value. Default: 0 (no maximum). |
The override flags (OverridePhonemes, OverrideExpressions, OverrideModifiers) are useful for preventing conflicts. When enabled, any morph of that type that isn't being set by your preset will be forced to zero. This stops other mods or the game from fighting over the same facial morphs.
Effects
Each preset contains one or more effects defined as [[FacialPreset.Effects]]. An effect tells the system to adjust a specific facial morph. There are four types:
Phoneme — Mouth Shapes
Phonemes control lip sync and mouth shape morphs. Index range: 0–15. See the morph reference for what each index does.
[[FacialPreset.Effects]] Type = "Phoneme" Index = 1 # BigAah — wide open mouth TargetValue = 0.8
Expression — Emotional Morphs
Expressions control broad emotional states like anger or pain. Index range: 0–16.
[[FacialPreset.Effects]] Type = "Expression" Index = 15 # Combat Shout TargetValue = 0.6
Modifier — Auxiliary Morphs
Modifiers control things like brow movement, squinting, and blinking. Index range: 2–13 (indices 0 and 1 are reserved by the engine).
[[FacialPreset.Effects]] Type = "Modifier" Index = 12 # Squint Left TargetValue = 0.5
MFEE — Custom Expressions (Mu Facial Expression Extended)
If you have the MFEE mod installed, you can use custom morph names instead of numeric indices. See the MFEE section for details.
[[FacialPreset.Effects]] Type = "MFEE" MorphCategory = "Misc" MorphName = "Biting_lips" TargetValue = 100
Standard Phoneme, Expression, and Modifier values use a 0.0–1.0 scale. Values above 1.0 will not apply correctly. MFEE effects use a 0–100 integer scale instead.
Effect Properties
These go under each [[FacialPreset.Effects]] entry.
| Property | Type | Description |
|---|---|---|
| Type | string | Required "Phoneme", "Expression", "Modifier", or "MFEE". |
| Index | integer | Which morph to control. Required for Phoneme, Expression, Modifier types. Not used for MFEE. |
| MorphCategory | string | MFEE only. The category the morph belongs to (e.g. "Misc", "Expressions"). |
| MorphName | string | MFEE only. The name of the custom morph (e.g. "Ahegao", "Biting_lips"). |
| TargetValue | float | The value the morph should reach at maximum intensity. 0.0–1.0 for standard types, 0–100 for MFEE. Default: 1.0. |
| MinTargetValue | float | Used with depth scaling. The starting value at MinPenetrationDepth. Default: 0.0. |
| MinPenetrationDepth | float | Depth at which this effect starts applying (the morph is at MinTargetValue). Default: 0.0. |
| MaxPenetrationDepth | float | Depth at which this effect reaches full TargetValue. Must be greater than MinPenetrationDepth for scaling to work. Default: 0.0. |
Depth Scaling
The most powerful feature of the system is depth-based scaling, which smoothly interpolates morph values based on how deep the penetration currently is. This makes expressions feel dynamic and reactive.
To use depth scaling, set both MinPenetrationDepth and MaxPenetrationDepth on an effect. The morph value will smoothly transition from MinTargetValue to TargetValue as depth increases through that range.
[[FacialPreset.Effects]] Type = "Expression" Index = 7 MinTargetValue = 0.2 # Value at minimum depth TargetValue = 1.0 # Value at maximum depth MinPenetrationDepth = 2.0 # Effect starts at depth 2 MaxPenetrationDepth = 10.0 # Effect reaches full power at depth 10
If you omit the depth properties (or set both to 0), the effect simply applies at the full TargetValue whenever the preset is active, regardless of depth.
You can combine multiple effects with different depth ranges in one preset. For example, start with a subtle expression at shallow depth, then layer on additional morphs at deeper penetration for a progressive reaction.
Scene Contexts
Use the Contexts property on a preset to restrict it to specific types of scenes. Context values are provided by the animation framework (like OStim or SexLab). If a preset has no Contexts, it matches any scene.
| Context | Description | |
|---|---|---|
| Vaginal | Scene involves vaginal penetration | |
| Anal | Scene involves anal penetration | |
| Oral | Scene involves oral penetration | |
| Aggressive | Scene is tagged as aggressive/rough | |
| FemDom | Scene is tagged as female-dominant | |
| Loving | Scene is tagged as loving/gentle | |
| Dirty | Scene is tagged as dirty/kinky | |
| Boobjob | Scene involves a boobjob | |
| Handjob | Scene involves a handjob | |
| Footjob | Scene involves a footjob | |
| Masturbation | Scene involves masturbation | |
You can combine multiple contexts. The preset will only activate when all specified contexts are present in the scene:
[[FacialPreset]] Targets = ["Vagina"] Contexts = ["Aggressive"] # Only during aggressive scenes Priority = 5
Morph Reference
Phonemes (0–15)
Expressions (0–16)
Modifiers (2–13)
MFEE Integration
If you have Mu Facial Expression Extended installed, you can use custom morph names for much more expressive results. Instead of Index, you specify a MorphCategory and MorphName.
MFEE morphs use an integer 0–100 scale, unlike the 0.0–1.0 scale used by standard Phoneme/Expression/Modifier types. Make sure you adjust your values accordingly.
[[FacialPreset.Effects]] Type = "MFEE" MorphCategory = "Expressions" MorphName = "Ahegao" TargetValue = 100 [[FacialPreset.Effects]] Type = "MFEE" MorphCategory = "Misc" MorphName = "Biting_lips" MinTargetValue = 10 TargetValue = 100 MinPenetrationDepth = 0.0 MaxPenetrationDepth = 12.0
Available morph categories and names depend on the MFEE morphs installed for your character's head mesh. Common ones include "Ahegao", "Biting_lips", "Puzzled", "Stress", and "EXPR2_Mouth_Open_Wide".
How Presets Are Selected
When a scene is active, the system picks one winning preset per actor. Here's how it decides:
1 Target matching — the preset's Targets must include at least one orifice that is currently being penetrated.
2 Condition checks — if the preset specifies Contexts, PenisSizeMin/Max, or PenisGirthMin/Max, those conditions must all pass.
3 Priority — among all matching presets, the one with the highest Priority value wins.
Say you have two vaginal presets: one for normal scenes at priority 2, and one for aggressive scenes at priority 5 with Contexts = ["Aggressive"]. During an aggressive scene, the priority 5 preset wins because it matches and has higher priority. During a normal scene, the aggressive preset doesn't match (context check fails), so the priority 2 preset wins instead.
Example: Basic Mouth Opening
This is the default configuration that ships with the mod. It uses a combination of phonemes to create a natural open-mouth look during oral scenes. Since SexLab already handles some mouth animation, this preset is optional.
Targets the mouth with very high priority. Uses OverridePhonemes to zero out all phonemes not defined here, preventing conflicts. Combines multiple phoneme shapes (Aah, BigAah, Eee, Eh, FV, K) to create a blended open mouth look.
[[FacialPreset]] Targets = ["Mouth"] Priority = 99999 OverrideExpressions = false OverrideModifiers = false OverridePhonemes = true Smoothing = 8.0 [[FacialPreset.Effects]] Type = "Phoneme" Index = 0 # Aah TargetValue = 0.75 [[FacialPreset.Effects]] Type = "Phoneme" Index = 1 # BigAah TargetValue = 0.75 [[FacialPreset.Effects]] Type = "Phoneme" Index = 5 # Eee TargetValue = 1.0 [[FacialPreset.Effects]] Type = "Phoneme" Index = 6 # Eh TargetValue = 1.0 [[FacialPreset.Effects]] Type = "Phoneme" Index = 7 # FV TargetValue = 1.0 [[FacialPreset.Effects]] Type = "Phoneme" Index = 9 # K TargetValue = 0.68
Example: Advanced Multi-Orifice Presets
These examples show more complex setups using depth scaling, MFEE morphs, context filtering, and size-based conditions.
Opens the mouth wider as depth increases, uses a Combat Shout expression that scales with depth, and adds an angry expression at deep penetration. All three override flags are on to prevent any other morphs from interfering.
[[FacialPreset]] Targets = ["Mouth"] Priority = 999229 OverrideExpressions = true OverrideModifiers = true OverridePhonemes = true Smoothing = 5.0 # Combat Shout expression: faint at surface, full at depth 12 [[FacialPreset.Effects]] Type = "Expression" Index = 15 MinTargetValue = 0.3 TargetValue = 1.0 MinPenetrationDepth = 0.0 MaxPenetrationDepth = 12.0 # MFEE wide mouth: opens between depth 0–8 [[FacialPreset.Effects]] Type = "MFEE" MorphCategory = "Misc" MorphName = "EXPR2_Mouth_Open_Wide" MinTargetValue = 70.0 TargetValue = 90.0 MinPenetrationDepth = 0.0 MaxPenetrationDepth = 8.0 # Angry look kicks in only at deep penetration (8.5–10) [[FacialPreset.Effects]] Type = "MFEE" MorphCategory = "Misc" MorphName = "MoodAnger" MinTargetValue = 0.0 TargetValue = 100.0 MinPenetrationDepth = 8.5 MaxPenetrationDepth = 10.0
Same orifice as above, but only activates when girth is 1.4 or higher. Has a slightly higher priority (999239 vs 999229) so it wins over the normal oral preset when the size condition is met. Notice the mouth opens even wider (90–100 vs 70–90).
[[FacialPreset]] Targets = ["Mouth"] PenisGirthMin = 1.4 Priority = 999239 OverrideExpressions = true OverrideModifiers = true OverridePhonemes = true Smoothing = 5.0 [[FacialPreset.Effects]] Type = "MFEE" MorphCategory = "Misc" MorphName = "EXPR2_Mouth_Open_Wide" MinTargetValue = 90.0 TargetValue = 100.0 MinPenetrationDepth = 0.0 MaxPenetrationDepth = 8.0 [[FacialPreset.Effects]] Type = "MFEE" MorphCategory = "Misc" MorphName = "MoodAnger" MinTargetValue = 0.0 TargetValue = 100.0 MinPenetrationDepth = 8.5 MaxPenetrationDepth = 10.0 [[FacialPreset.Effects]] Type = "Expression" Index = 16 MinTargetValue = 0.4 TargetValue = 1.0 MinPenetrationDepth = 0.0 MaxPenetrationDepth = 12.0
Combines two Expression effects with four Modifier effects. The expressions provide the base emotional look, while the modifiers add brow furrowing and squinting that kick in at deeper penetration (depth 4+).
[[FacialPreset]] Targets = ["Anus"] Priority = 22 OverrideExpressions = true OverrideModifiers = true OverridePhonemes = true # Combat Shout scales from subtle to strong over depth 0–12 [[FacialPreset.Effects]] Type = "Expression" Index = 15 MinTargetValue = 0.1 TargetValue = 1.0 MinPenetrationDepth = 0.0 MaxPenetrationDepth = 12.0 # Secondary expression for extra intensity at deep penetration [[FacialPreset.Effects]] Type = "Expression" Index = 16 MinTargetValue = 0.0 TargetValue = 0.4 MinPenetrationDepth = 0.0 MaxPenetrationDepth = 16.0 # Squint left/right — only at deeper penetration [[FacialPreset.Effects]] Type = "Modifier" Index = 12 # Squint Left TargetValue = 0.5 MinPenetrationDepth = 4.0 MaxPenetrationDepth = 12.0 [[FacialPreset.Effects]] Type = "Modifier" Index = 13 # Squint Right TargetValue = 0.9 MinPenetrationDepth = 4.0 MaxPenetrationDepth = 6.0 # Brow down left/right — furrowed brows at depth [[FacialPreset.Effects]] Type = "Modifier" Index = 2 # Brow Down Left TargetValue = 0.5 MinPenetrationDepth = 4.0 MaxPenetrationDepth = 6.0 [[FacialPreset.Effects]] Type = "Modifier" Index = 3 # Brow Down Right TargetValue = 0.9 MinPenetrationDepth = 4.0 MaxPenetrationDepth = 7.0
Two presets for vaginal penetration. The first (priority 2) activates during any vaginal scene and plays a lip-biting expression. The second (priority 5) only activates during aggressive scenes and overrides the first with a stressed/puzzled look. This shows how Contexts and Priority work together.
# Vagina — default (any scene) [[FacialPreset]] Targets = ["Vagina"] Priority = 2 OverrideExpressions = true OverrideModifiers = true OverridePhonemes = false [[FacialPreset.Effects]] Type = "MFEE" MorphCategory = "Misc" MorphName = "Biting_lips" MinTargetValue = 1.0 TargetValue = 100.0 MinPenetrationDepth = 0.0 MaxPenetrationDepth = 12.0 # Vagina — aggressive scenes only (higher priority wins when context matches) [[FacialPreset]] Targets = ["Vagina"] Priority = 5 Contexts = ["Aggressive"] OverrideExpressions = true OverrideModifiers = true OverridePhonemes = false [[FacialPreset.Effects]] Type = "MFEE" MorphCategory = "Misc" MorphName = "Puzzled" MinTargetValue = 10.0 TargetValue = 100.0 MinPenetrationDepth = 0.0 MaxPenetrationDepth = 10.0 [[FacialPreset.Effects]] Type = "MFEE" MorphCategory = "Misc" MorphName = "Stress" MinTargetValue = 0.0 TargetValue = 80.0 MinPenetrationDepth = 8.0 MaxPenetrationDepth = 10.0