Characters & assets

Touches

Make one person touch, hold or kiss another on the spot, almost anywhere on the body, from Lua, with nothing animated beforehand.

A touch is made on the spot: one person looks, comes to the right place, reaches and puts a hand (or their lips) on the other, on their skin, whoever they are, then lets go. Nothing is animated beforehand. The hand finds the other body (tall or short, slim or heavy) and the touch plays on top of what both are doing, so an idle keeps breathing under it.

luaif Actor:Interaction("touchShoulder", Player) then
    Game:Say(Actor, "Hey. You okay?")
end
Actor:Interaction("holdHand", Player)
Actor:Interaction("kiss", Player)
Actor:StopInteraction()          -- let go now

Interaction returns false when it cannot happen, with the reason in the log: the name is unknown, or the spot is out of reach from anywhere nearby. A person who cannot reach is refused, never left with a hand in the air.

Where the toucher goes

Before anything moves, the touch is tried, whole, from several places and postures, and the cheapest that reaches wins:

  • Where they stand, or a step closer (up to 35 cm, never into the other person).
  • Round to face the spot: the back of a thigh is touched from behind, the side of a hip from the side. The toucher walks round the other person, not through them, and the hand waits until they are there.
  • Standing, on tiptoe, crouched or kneeling: a calf, a foot or a kiss on the belly bring the toucher down; a tall person's shoulder brings them up on their toes. The feet stay planted.

Staying put beats moving, standing beats tiptoe, tiptoe beats crouching, crouching beats kneeling. After a hug or a short step in, the toucher steps back; somewhere they walked round to, they stay. Further than about half a metre away, walk them over first with Actor:moveToPerson(Player).

Picking things up

The same walk, crouch and reach take things too: the pieces a room set's catalog.ulset marks handheld (mugs, cups, glasses, bottles, phones, books, cutlery...).

luaif Actor:PickUp("Coffee_Mug") then    -- the nearest one within 3 m
    Game:Say(Actor, "Coffee?")
end
-- later
Actor:PutDown()                       -- back where it was

Something standing (a mug, a bottle, a glass) is taken round its side, the fingers closing round it; something lying flat (a phone, a book, a fork) from above. It is carried upright in front of the body, the palm turned in, until PutDown. Something wider than about 30 cm needs two hands, which is not done yet.

The touches that ship

Name What it does
touchArm A hand on the upper arm.
touchShoulder A hand on the shoulder, looking at the face.
caressFace A hand on the cheek, stroking.
touchChin Fingers under the chin.
strokeHair A hand stroking the back of the head.
patHead A few pats on the top of the head.
touchNape A hand on the back of the neck.
touchChest A hand flat on the chest.
touchBreast, caressBreast A hand on a breast, resting or stroking.
cupBreasts Both hands, one on each breast.
touchBelly A hand stroking the belly.
holdHips Both hands on the hips.
touchButt A hand on a buttock (goes round to reach it).
grabButt Both hands on the buttocks.
touchLeg A hand on the front of the thigh, stroking.
touchInnerThigh A hand on the inside of the thigh.
touchCalf A hand on the calf, crouching for it.
hug Steps in chest to chest, both arms around the other's back; the other hugs back.
holdHand Takes the other's hand; they take it back. Face to face, one hand lies palm up and the other rests on it; side by side, the palms press together.
kiss Lips to lips, heads tilted, eyes closed; the other kisses back.
kissTender The same with a hand on the cheek.
kissCheek, kissForehead, kissNeck, kissShoulder, kissBreast, kissBelly A kiss on that place.

Making your own

A touch is a file in your mod's Interactions/ folder, named after it: Interactions/squeezeArm.ulinteract.

json{ "zone": "upper_arm", "side": "near", "hand": "near",
  "reach": 0.7, "hold": 2.0, "release": 0.6,
  "motion": "rest", "look": "target", "reaction": "look", "grip": 0.4 }
Field What it means
zone Where on the other body, a name from a .ulzones file (below).
side Which side of the other body: near (the side facing the toucher), far, left, right.
hand Which hand touches: near (the one closer to the spot), left, right.
part What touches: hand (default) or mouth. With mouth the spine, neck and head bring the lips there: a kiss.
reach Seconds to bring the hand there, once the toucher is in place.
hold Seconds it stays. -1 stays until Actor:StopInteraction().
release Seconds to let go.
motion What the hand does while there: rest, caress (strokes along the skin), pat (taps).
look Where the toucher looks: target (the spot, then the face), face, none.
reaction look: the touched person looks at the hand, then at the toucher. none: they do not react.
gap Centimetres between palm (or lips) and skin (default 0.8).
grip How far the fingers close while there, 0 (open) to 1 (a firm grip).
closeEyes true: the toucher's eyes close while there (a kiss).
tilt Degrees the head tilts for a kiss on the lips, so the noses pass.
posture auto (default: stand if that reaches, else tiptoe, crouch, kneel), stand, tiptoe, crouch, kneel. With no zone and no contacts, also bend (see below).
sit Kneeling: how far back she sits, 0 (upright on the knees) to 1 (on her heels). Bending: how far over, 0..1 of about 80 degrees (default 1).

A posture alone

A touch with no zone and no contacts is only a posture, taken facing the other person (or, for bend, turned away from them), hands left to the animation playing. Use it to kneel before someone, or to bend over in front of them:

json{ "posture": "kneel", "sit": 0.7, "reach": 1.2, "hold": -1, "release": 1.0, "look": "face", "reaction": "look" }
json{ "posture": "bend", "sit": 1.0, "reach": 1.2, "hold": -1, "release": 1.0, "look": "none" }

posture is kneel, crouch or bend. Kneeling lowers the whole body and folds the legs under it; the hips and thighs then stay put while the upper body keeps its idle. Bending turns the body round and folds the spine forward from the waist, legs straight. Both ship in ul_Base as kneel and bend: Actor:StartInteraction("kneel", other), then Actor:StopInteraction() to get up.

Several hands, meeting, and touches given back

A touch can use several hands (and the mouth), each with its own place: list them under contacts. This is the hug that ships:

json{
  "contacts": [
    { "zone": "back_side", "hand": "left",  "side": "near", "elbow": "out" },
    { "zone": "back_side", "hand": "right", "side": "near", "elbow": "out" }
  ],
  "close": 22, "mutual": true,
  "reach": 0.9, "hold": 3.0, "release": 0.8,
  "motion": "rest", "look": "none", "reaction": "none"
}

And the kiss, where the lips do not go onto a zone but meet the other's halfway:

json{ "contacts": [ { "part": "mouth", "meet": true } ],
  "mutual": true, "close": 26, "closeEyes": true, "tilt": 14, "gap": 0.5,
  "reach": 1.0, "hold": 2.5, "release": 0.8, "look": "none", "reaction": "none" }
Field What it means
contacts One entry per hand or mouth, each with its own zone, side, hand, part, elbow and meet. With a hand named, near is the side facing that hand: the left hand goes to the other's right side.
elbow natural (the way the elbow bends now) or out (away from the body, to wrap an arm around someone instead of through them).
meet true: no zone; this hand or the lips meet the other person's halfway (a hand held, a kiss). Needs mutual, since the other has to come halfway too.
close How far apart the chests end up, in cm; the toucher steps in for it (a hug is about 22). Without it, the toucher finds their own place (above).
mutual The other person does the same touch back, a beat later, and lets go with the first.

A file with the same name in a mod later in the load order replaces it.

Gestures in a sex scene

During a sex scene, a left click on the couple opens a half circle over them. Its first level is the gesture families, plus Slower, Faster and Finish. Its second level is the gestures of that family. A gesture is a touch with a family, and every mod's touches with one are offered.

A gesture plays on top of the position: both bodies keep playing their clip, and only the arm (or the head, for the mouth) of the one who does it leaves the clip for the touch. The player's person does it to the partner.

A gesture is started from where the body is, as the position holds it:

  • there is no step, no turn and no crouch;
  • if the spot is out of reach in that position, the petal is shown dimmed with the reason ("butt is 12 cm out of reach in this position");
  • a hand that holds the body up (on all fours, propped on a hand) is never taken: the other hand is used, or the gesture is refused ("the left hand holds the body up").

A second click on the gesture lets go.

json{ "family": "hands", "label": "Spank",
  "contacts": [ { "zone": "butt", "side": "near", "hand": "near" } ],
  "reach": 0.45, "hold": -1, "release": 0.5,
  "motion": "strike", "period": 0.85, "strike": 20,
  "look": "target", "reaction": "flinch", "gap": 0.3 }
Field What it means
family The half circle's first-level petal it goes under: hands, mouth, or your own. No family: not offered in scenes.
label The petal's text (default: the file name).
motion Besides rest, caress and pat: strike (drawn back off the skin, then brought down fast, again and again: a spank, a slap), squeeze (a grip that tightens in pulses), pull (held and drawn toward the toucher: hair).
period strike: seconds per blow (default 0.9).
strike strike: how far the hand is drawn back, cm (default 16).
reaction Besides look and none: flinch (a jolt of the back and the head at every blow) and headBack (the head drawn back by pull degrees: hair pulled, a hand on the throat). On top of the touched person's clip.
pull headBack: degrees (default 18).
enter The parts of the other body the hands may go into, by hull part name (see below): ["pelvis"] for fingering. Everywhere else the hands are kept out of the skin.

Gestures that ship (ul_Base/Interactions/Scene/):

Name Family What it does
spank hands The nearest free hand spanks the buttock, again and again; she jolts at each blow.
choke hands One hand round the front of the throat (zone throat), tightening; her head tips back.
chokeTwoHands hands Both hands on the sides of the neck. Needs both hands free.
pullHair hands A fist in the hair, drawn back; the head comes with it.
slap hands An open hand across the cheek, repeated; the head jolts.
grabHips hands Both hands clamped on the hips, gripping in pulses. Needs both hands free.
grabBreast hands A hand closed round the breast, squeezing.
coverMouth hands A palm over the mouth, the head pushed back a little.
sceneKiss mouth The lips onto the other's, eyes closed.
sceneKissNeck mouth The mouth on the side of the neck, eyes closed.

Lua cannot start a gesture in place yet: Actor:Interaction(...) still steps and turns the toucher, which breaks a position.

Bodies and joints

Two rules apply to every touch and every gesture, whatever the IK asked for:

  • A hand never goes into a body, the other's or the toucher's own. Each body is measured as a set of tubes, one per part (pelvis, abdomenLower, chestUpper, neckUpper, head, and per side lShldrBend, lForearmBend, lHand, lThighBend, lShin, lFoot, and the same with r). The tubes follow the skin and the body's shape (a heavier belly, a bigger chest), and the arm bends so that the palm and the fingertips stay on the skin. A gesture's enter lists the parts it may go into.
  • No joint turns further than a person's can. Anims/JointLimits.json gives each joint its range, in degrees from the rest pose and relative to its parent: twist about the bone, swing_a and swing_b across it. A hinge (knee, elbow, finger) has hinge, the axis it bends about (left, forward, up), and swing_a is then its bend; any other joint names with axis which body direction swing_a turns about (left, forward or up). The shipped ranges were measured from every animation in the game (-JointLimitsAudit), with the twist and sideways bend of hinges capped by anatomy (Tools/Animation/joint_limits_caps.py). A mod's file replaces the joints it names.

The limits only hold back what the hand placement adds: a joint the animation itself already takes further is left as played. A hand that needs more turn than the wrist has gets it from the forearm, and an elbow bent sideways from the upper arm turning, as in a body. When no human pose reaches the spot, the hand stops short rather than breaking a joint to get there.

json{ "joints": {
   "lForearmBend": { "hinge": [0.649, 0.258, 0.716], "twist": [-15, 15], "swing_a": [-8, 129], "swing_b": [-15, 15] },
   "head": { "axis": "left", "twist": [-31, 33], "swing_a": [-35, 44], "swing_b": [-42, 41] }
} }

ul.JointLimits 0 and ul.BodyHull 0 turn either rule off (to compare); ul.JointLimitsLog 1 logs every correction.

Zones

Zones name places on a body. They live in .ulzones files in any mod's Interactions/ folder; zones from every mod are merged by name, so you can add your own or redefine one.

json{
  "upper_arm": { "bone": "{s}ShldrBend", "toward": "{s}ForearmBend", "along": 0.45, "dir": [0.7, 0.7, 0.1] },
  "head_top":  { "bone": "head", "toward": "", "along": 0.0, "dir": [0.1, 0.0, 1.0] }
}
Field What it means
bone The Genesis 8 bone the zone is on. {s} is the side, l or r.
toward The next bone along the limb. Empty for a bone on its own, like the head.
along How far from bone toward toward, 0 to 1.
dir Which way the skin faces there, as [front, out, up] in the body's own frame: [1, 0, 0] is the front, [0, 1, 0] the outside of that side, [0, 0, 1] the top.

The hand goes onto the outermost skin in that direction, found on the actual body with its shape, and follows it as the person moves. The palm always faces the skin, the fingers carrying on from the forearm.

Zones that ship:

  • Head and neck: head_top, hair, forehead, cheek, ear, chin, lips, neck, throat, nape.
  • Arms: shoulder, collarbone, upper_arm, forearm, hand.
  • Front: chest, breast, breast_under, breast_side, stomach, belly, waist, crotch.
  • Back: upper_back, shoulder_blade, back_side, lower_back, butt, butt_low.
  • Legs: hip, thigh_front, thigh_outer, thigh_inner, thigh_back, knee, shin, calf, ankle, foot.

Grips: how a hand takes a thing

Actor:pickUp puts a hand on an object. Without more information the game guesses from the object's size: something standing (a mug, a bottle) is taken round its side, something flat (a phone, a book) from above, and anything longer than a hand's span is refused. A piece can say better, with grip markers in its .ulmat (see Rooms, Surfaces of the generated furniture):

json"grips": [
  {"name": "Main", "kind": "trigger", "hand": "r", "pos_cm": [-4.0, 0.0, 6.2], "normal": [-0.97, 0, 0.24], "fingers": [0, 1, 0]},
  {"name": "Support", "kind": "two_hand", "hand": "l", "pos_cm": [57.0, 0.0, 4.9], "normal": [0, 0, -1], "fingers": [0, -1, 0], "curl": 0.7}
]
Field What it means
name Main is the hand that holds it; Support the second hand of a long gun or a chainsaw (not used yet).
kind How the fingers close, a name from a .ulgrips file (below): power, pinch, tripod, key, hook, platform, spherical, trigger, two_hand.
hand r, l, or any. A grip for either hand has its fingers flipped when the left hand takes it. A pistol's grip is r: the person uses that hand.
pos_cm Where the palm centre rests, on the surface, in centimetres from the piece's origin (x right, y back, z up, front toward −y, like points).
normal The surface normal there, out of the object: the palm faces the other way.
fingers Which way the straight fingers point before they curl, at right angles to normal.
curl Optional, 0 to 1: overrides the kind's closure.

Grip kinds live in .ulgrips files in any mod's Interactions/ folder, merged by name like zones:

json{
  "power":   { "curl": 0.85, "gap": 1.6 },
  "pinch":   { "curl": 0.35, "gap": 0.8 },
  "trigger": { "curl": 0.80, "gap": 1.5, "index_out": true }
}

curl is how far the fingers close toward the palm, gap the centimetres the palm stays off the surface, and index_out keeps the index finger straight (a trigger finger along the frame). Add a kind, or redefine a shipped one, by shipping your own file.

A zone needs a bone the body's skin is weighted to: lGlute/rGlute only drive the jiggle, which is why butt sits on pelvis.

Rigged things: a whip that hangs, swings and cracks

A piece that bends (a whip, a belt, a leash, a chain, a flogger's falls, a cane that flexes) ships twice: the .glb the room places, posed as it lies (coiled on the table), and <piece>__rig.glb beside it, the same thing on a bone chain in its rest pose with named clips as glTF animations. The .ulmat names it:

json"rig": {"file": "Product_Whip_Bull_Black__rig", "bones": 32, "clips": {"Hang": 1.0, "Swing": 2.0, "Crack": 1.0, "Coiled": 0.1}}

When a person picks such a piece up, the game swaps the rigged twin in and loops its Hang clip, so the whip drops from the hand instead of staying coiled in it; putting it down brings the static back. Actor:heldClip("Crack") plays any other clip of the held thing once (Actor:heldClip("Swing", true) loops it). Clip names are the piece's own: the shipped families use Hang, Swing, Crack for hanging things, Flex for canes and crops, Coiled for the lying pose. A modder's rigged .glb needs only a skin and animations named in the sidecar; the materials come from the static's painted zones by slot name.

Limits

  • A short person reaches a tall one's head only as far as tiptoes take them: the other does not bow their head yet.
  • The hand rests on the skin, not on clothes: a thick garment is pressed into.
  • Outside the scene reactions (flinch, headBack), the touched person only looks; they do not react with the body.