Actor API
Every method of a person handle: the player, Actor, and anyone a lookup returns.
Every person a script touches is a person handle with these methods: Player, Actor, and whatever Game:getSpecific, Game:generatePerson and the other lookups return. See People for a guided tour. Methods added by mods through ActorMethods (such as ul_Health's infect) are not listed here: see each mod's description.
Identity
Actor:behavior(id) → number | nil#How strongly their personality pushes towards a behaviour ("helping", "deception", "revenge"…, the behaviors of Personality/*.ulpersonality), raised or lowered by the pressure they are under. nil for an unknown behaviour.
Actor:GetGenderedWord(ifMale, ifFemale) → text#The first word for a man, the second for a woman.
Actor:GetGenderedWord("boyfriend", "girlfriend")Actor:getID() → number#A short numeric id, usable with Game:getSpecific(id).
Actor:getRace() → text#Fantasy race: Human (default), Elf, Orc, Vampire.
Actor:GetToken(token) → text#A name or pronoun for dialogue: name, name_last, S/s (he/she), O/o, P/p, PP/pp, R/r, relationship, callplayer, Major, or any male_or_female pair.
Actor:GetToken("s")Actor:hasTrait(id) → boolean#Whether one of their selected traits is id ("hotheaded", "patient"…, the traits of Personality/*.ulpersonality).
if Actor:hasTrait("hotheaded") then ... endActor:id() → text#A unique id for this person (stable across saves).
Actor:isCreature() → boolean#True if this is a creature rather than a person.
Actor:isCreatureType(type) → boolean#True if this is a creature of that type ("Dog", "Horse", "Tentacles").
Actor:isEthnic(ethnicity) → boolean#Ethnicity check: arab, asian, black, indian, latin, white.
Actor:isFemale() → boolean#Presented gender is female.
Actor:isMale() → boolean#Presented gender is male.
Actor:isRace(race) → boolean#Fantasy race check.
Actor:isSameAs(other) → boolean#True when both handles are the same person.
Actor:isSameEthnic(other) → boolean#Same ethnicity.
Actor:isSameGender(other) → boolean#Both have the same presented gender.
Actor:isSameRace(other) → boolean#Same fantasy race.
Actor:isTrans() → boolean#Their body differs from their presented gender.
Actor:isValid() → boolean#False for the invalid person a failed lookup returns, or a person no longer in the world. Check it before using someone you looked up.
Actor:name() → text#First name.
Actor:raceToString() → text#Display text for their ethnicity.
Also callable as StringToRace.
Actor:setName(first, last?)#Sets the name; last may be nil to leave it.
Actor:setName("Chloé", "Martin")Actor:setRace(race)#Sets the fantasy race.
Actor:trait(name) → number | nil#One personality value, 0 to 1: a facet ("openness", "jealousy", "cruelty"…) or a value the social simulation keeps for them. nil for a name nobody defines. Facets are mod data in Personality/*.ulpersonality.
if (Actor:trait("jealousy") or 0.5) > 0.7 then ... endActor:traits() → { id… }#Their selected trait ids (five by default, selectionCount).
Stats
Actor:addBuff({ stat = value, ... }, minutes) → bool#Raises the stats for that many game minutes, then takes it back: a coffee's lift and its dip. Each call stacks, and the player's buffs are saved. The scene version of an action's BUFF effect, for when the amount depends on a choice.
Actor:addCondition(id [, cause]) → bool#Gives this person a lasting condition defined in a mod's Conditions/*.ulconditions: saved with them, read by any mod, slowing their walk, keeping their pain from healing below its level and taking the positions it lists out of sex scenes. False for an unknown id or one already held. Fires conditionChanged.
Player:addCondition('limp', 'hit by a van')Actor:addStatModifier(id, stat, value) / addStatModifier(id, { stat = value, ... }) → bool#A bonus (or malus) on top of the stat's base value, under an id your mod picks (prefix it with your mod's name). Saved with the person, never written into the base value, and gone with removeStatModifier(id); the same id again replaces it. getStat includes every modifier and worn garment, getBaseStat does not. Use it for perks, worn items, a course of treatment: anything that should come off exactly as it went on.
Player:addStatModifier("mymod_glasses", { intelligence = 2, attractiveness = 1 })Actor:getBaseStat(stat) → number#The stat without modifiers or worn clothes. setStat takes the value with them (like getStat returns it), so setStat(s, getStat(s) + 1) moves the base by one and never bakes a bonus in.
local natural = Player:getBaseStat("attractiveness")Actor:getConditions() → { { id, name, text, since, cause, pain, speed, module } }#Every lasting condition they hold, with when (game hours) and why.
for _, c in ipairs(Player:getConditions()) do Game:Log(c.name) endActor:getStat(stat) → number#A stat's value.
Player:getStat("mood")Actor:GetStatInt(stat)#GetStat rounded down to a whole number.
Actor:getStatModifiers() → table#Every modifier on them: { [id] = { stat = value, ... } }, perks included (perk:<id>).
for id, stats in pairs(Player:getStatModifiers()) do ... endActor:GetStatString(stat)#GetStat as text.
Actor:hasCondition(id) → bool#Whether they hold that lasting condition now, whichever mod gave it.
if Player:hasCondition('chair') then Game:Narrate('The step is a wall.') endActor:hasStatModifier(id) → bool#Whether a modifier of that id is on them.
if not Player:hasStatModifier("mymod_glasses") then ... endActor:isInterestedInRace(other) → boolean#Whether they like other's ethnicity (always true without the Interracial module).
Actor:modifyRaceFetish(other, min, max?)#Adds a random amount to their liking for other's ethnicity (the likes_<ethnicity> stat).
Actor:modifyStat(stat, amount)#Adds to a stat (negative to remove). Scaled by difficulty for stats marked HIGHER_BETTER, unless the scene called Game:PreciseModify().
Actor:modifyStat("rapportwithplayer", 5)Actor:removeCondition(id) → bool#Takes a lasting condition away (healed, a new hip). False when they did not have it.
Player:removeCondition('limp')Actor:removeStatModifier(id) → bool#Takes a modifier off. False when they had none under that id.
Player:removeStatModifier("mymod_glasses")Actor:setStat(stat, value)#Sets a stat (clamped to its range, never scaled by difficulty).
Memory
Actor:clearActorVar(key)#Removes the var, number or text, and the tag of the same name: Game:getPerson(key) no longer finds this person. setActorVar(key, 0) kept the key.
Actor:getActorVar(tag) → boolean#Whether the person carries that tag.
Actor:getVar(key) → value#A stored value, or nil if never set.
Actor:setActorVar(tag, true)#Marks this person with a tag so Game:getPerson(tag) finds them from any scene (a storyline's NPC).
Actor:setVar(key, value)#Stores a number, text or true/false on this person, saved with them. nil deletes it. Keys are shared by all mods: prefix them.
Actor:setVar("ynl_met", 1)History
Actor:hasEvent(type) → number#How many times that event happened to them (0 = never).
Actor:history() → list#Their events, newest first: { type, text, date, count, major, icon }.
Actor:record(type, other?, level?, params?) → boolean#Records a life event of a type from History/*.ulhistory. level is "major"/"minor"; params fills {key} placeholders. False when a unique event already happened between these two.
Actor:record("argued", Player, "major")Relationships
Actor:conversationSize()#How many are in this person's conversation, this person included; 1 when talking with nobody.
Actor:favoriteHome(add?)#Legacy. Does nothing yet: NPC homes are venue tags, not buildings.
Actor:getConversation()#The people this person is talking with right now (a chat in room life, a scene the room is playing, the player once joined), not this person. An empty list: talking with nobody.
Actor:getRelatedPerson(type, …) → person#Someone related to this person by one of those types (Dating, Spouses, Siblings, ParentChild…); nil if none.
Actor:hadRelationship(role, …) → boolean#Has ever been with anyone that way, exes included.
Actor:hadSex() → boolean#Has had sex with the player in this playthrough.
Actor:hasRelationship(role, role?, role?) → boolean#Has any of these roles with the player: Dating, Spouses, Affair, Colleagues…
Actor:homeBuilding()#The id of the home this person lives in, "" when none on the map (they live with the player, or off the map).
Actor:isBoss() → boolean#The player's boss.
Actor:isColleague() → boolean#The player's colleague.
Actor:isContactExchanged() → boolean#In the player's contacts.
Actor:isDating(other?) → boolean#They date the player (or other).
Actor:isDistracted()#True while this person is talking in a scene the player is watching (two people in conversation, in the room). An easier mark: ul_tc_pickpocket is noticed far less often. Works in NPC scenes too; false for anyone the player is not watching.
Actor:isEmployee() → boolean#The player is their boss.
Actor:isExRelative(other?) → boolean#An ex of the player (or other).
Actor:isInCircle([other]) → boolean#A number was exchanged or any bond exists (family, colleague, date, a role); no argument means the player. Use it instead of isContactExchanged() to hide offers like exchanging numbers from people the player already knows.
Actor:isInParty()#True while this person is with the player.
Actor:isLandlord() → boolean#The player's landlord.
Actor:isMarried() → boolean#They have a spouse.
Actor:isNeighbour() → boolean#The player's neighbour (same building).
Actor:isRelationshipWith(other, type, …) → boolean#An NPC-to-NPC relationship with other: ParentChild, Siblings, Cousins, GrandParentChild, Dating, Spouses.
Actor:isRelative(other?) → boolean#Family of the player (or other).
Actor:isRelativeType(type, …) → boolean#One of these relatives of the player: Parent, Child, Sibling, GrandParent, GrandChild, Cousin (up to five).
Actor:joinConversation(other)#This person joins the conversation other is in, out of their own (one is started for the two when other talks with nobody). The player joins with Game:joinConversation.
Actor:leaveConversation()#This person stops talking with the others; a conversation left with one person is over.
Actor:leaveHere(hours?) → bool#Out of the player's party but left at the current place for hours (default: until they come to). The way to put down someone carried in; leaveParty sends them home.
Actor:livesWithPlayer() → boolean#Shares the player's home (not just the building).
Relationship changes
Actor:addColleague()#Becomes the player's colleague.
Actor:addDatingFriend()#Becomes a friend with benefits.
Actor:addNeighbour()#Becomes the player's neighbour.
Actor:blockNpcRelationships()#This person never gets NPC-NPC relationships again: addNpcRelationship and getRelatedPerson skip them.
Actor:inviteHome(hours?)#This person invites the player into the home they live in for the next hours (12 by default): its PRIVATE actions (bathe, sleep, eat) are offered there. Returns false when they have no home on the map.
Actor:joinParty()#Joins the player's party: wherever the player goes, this person is there too, placed in the room with the other people. Up to 4 people. Returns false when full, already in, or the person is unknown. Same as startDate.
if not Actor:joinParty() then Game:Narrate("Your car is full.") endActor:leaveParty()#Leaves the party: they go back to their own day and leave the room the player is in.
Actor:matchLastName(other)#Takes other's last name.
Actor:passOn()#Hands this person to the next scene, which reads Game:getSpecific("PassedOn").
Actor:removeColleague()#No longer a colleague (stays an acquaintance).
Actor:removeDatingFriend()#No longer a friend with benefits.
Actor:removeNeighbour()#No longer the player's neighbour; stays an acquaintance.
Actor:setBoss()#Becomes the player's boss (the previous one is dropped).
Actor:setDating()#They become the player's partner.
Actor:setDatingId()#Selects this partner for the next Game:loseDating() (several partners).
Actor:setExRelative(other?)#Remembers they used to be related to other (the player by default).
Actor:setLandlord()#Becomes the player's landlord.
Actor:setLivingWithPlayer(on)#Moves in with the player (true) or back to a home of their own.
Actor:setPT()#Becomes the player's personal trainer.
Actor:setRelativeType(type)#Becomes that kind of relative of the player.
Actor:startDate()#This person comes along with the player (they join the party, see joinParty): they follow the player into every place until endDate, leaveParty, "Send home" or sleep. Returns false when the party is full. It does not make them a partner: that is setDating.
Orientation
Actor:isAsexual() → boolean#Asexual.
Actor:isDominantSex(other) → boolean#Leads by the legacy rules: gender, then anatomy, then the lower masochist stat.
Actor:isGay() → boolean#Only attracted to their own sex.
Actor:isInterestedIn(other) → boolean#Attracted to other's gender and body.
Actor:isInterestedInMen() → boolean#Attracted to men.
Actor:isInterestedInTrans() → boolean#Attracted to trans people.
Actor:isInterestedInWomen() → boolean#Attracted to women.
Actor:isStraight() → boolean#Only attracted to the other sex.
Actor:makeInterested(other)#Shifts their orientation so they are attracted to other.
Clothes
Actor:addClothing(id) → bool#Gives them a garment out of nowhere (a reward, a uniform). false when no .ulcloth defines the id.
Actor:changeInto(id, ...) → count#Puts these garments on over what they wear, with the outfit-change spin (the clothes change at its peak). Returns how many ids were found. dress(id) does the same without the spin.
Player:giveClothing(Actor, gift)
Actor:changeInto(gift)Actor:dress(id?, …)#No argument: an everyday outfit from Clothes/Outfits/outfits_F.txt / outfits_M.txt, or the sports or swim list at a gym, pool or beach. Item ids (up to eight): those garments, over what they wear ("Jeans_1" finds "Jeans_1_F" on a woman). One unknown name: that outfit list ("sports", "swim", "work").
Player:dress("Nice-Jeans_1_F", "Cute-Croptop_2_F")Actor:dressBondage(name?)#Puts restraints on over the clothes: a name of Clothes/Outfits/restraints.txt (Collar, Handcuffs, Thighcuffs, Shincuffs, Blindfold, Gag, Mask, Torso) or an item id. No name: collar and handcuffs.
Captive:dressBondage("Handcuffs")Actor:dressExcept(category, …)#Dresses them but leaves these categories as they are (up to six).
Actor:dressFormal()#The formal uniform: evening wear or a suit.
Actor:dressUniform(name?)#A uniform of Clothes/Outfits/uniforms.txt by name ("Police", "Nurse", "Crime", "Wedding", "sexwork"...) or by venue tag; no name means the uniform of where they are. Everyday clothes when none fits.
Cop:dressUniform("Police")Actor:getClothes() → { ids }#Every garment they own. Kept across rooms and saves for the player and every known person.
Actor:getOutfit(occasion) → { ids }#Their own outfit for an occasion (Clothes/Outfits/occasions.txt), empty when they have none. A location tag works too: "gym" means "sports".
Actor:giveClothing(Other, id) → bool#Hands one of their garments to Other, taking it off first if they wear it. false when they do not own it. From the player, it is remembered as a gift (isWearingGift).
Player:giveClothing(Actor, "Neon-Hoodie_1_F")Actor:isEquipped(slot) → boolean#Something is worn in that slot.
Actor:isNaked() → boolean#Wears nothing.
Actor:isWearingGift() → bool#Whether something the player gave them is on them right now.
Actor:ownsClothing(id) → bool#Whether that garment is theirs.
Actor:setNoRedress()#Keeps the current outfit after the scene instead of restoring the previous one.
Actor:setOutfit(occasion, { ids }, fromPlayer?)#Keeps these garments as their outfit for the occasion; any they do not own become theirs. {} forgets it. From then on they wear it whenever they dress for that occasion.
Actor:strip()#Removes everything.
Actor:stripOne(category)#Removes one category: Top, Bottom, Dress, Outerwear, Underwear, Shoes, Socks, Headwear, Accessory.
Actor:wearOutfit(occasion?, instant?) → bool#Puts on their outfit for the occasion (no occasion: the one where they are), with the outfit-change spin unless instant is true. false when they have none, and nothing changes.
Appearance
Actor:addFluid(area, type?, amount?) → bool#Lays a fluid on one area of the body (Face, Head, Chest, Belly, Back, Butt, Crotch, Arms, Legs): type a fluid of Fluids/fluids.json (Semen when left out), amount 0..1 (1). It dries over time and stays until washed. False when the area has no pieces (a male body takes none).
Victim:addFluid("Face", "Semen", 1)Actor:addInjury(name, severity?, days?) → bool#A visible bruise or cut: an image of Injuries/<Face|Torso|Arm|Leg>/ (black_eye_left, split_lip, stomach, thigh_right...; or "Face/name") painted over the skin. severity 0..1 (1), fades out over days (7; 0 = for good). Saved with the look.
Victim:addInjury("black_eye_left", 0.8, 6)Actor:addWound(bone, side?, severity?, kind?, by?) → bool#Opens a wound on the skin over bone (abdomenUpper, chestUpper, lThighBend...), side "front" (default) or "back", severity 0..1 (0.5), kind Stab (default), Slash, Stabs or Gunshot. The opening is painted there, blood runs down the body from it and drips to the floor, slowing over minutes; it browns as it dries and stays until washed. The body reacts: it holds the wound, or goes down when it is bad or in a leg; everyone near is frightened except by, who did it. False without a Blood fluid type (the ul_Blood mod off) or such a bone.
if Victim:addWound("abdomenUpper", "front", 0.8) then Game:Narrate("Blood spreads through his fingers.") endActor:blendAppearanceFrom(parentA, parentB)#Gives them a face blended from two parents.
Actor:blendPreset(preset)#Blends a character preset onto their current look.
Actor:blendPreset("situational/tanned")Actor:bloodied() → number#How much blood shows on them, 0 to 1: wounds and runs on the skin, stains on the clothes they wear, a wound still bleeding. About 0.3 is one wound; 1 is covered or bleeding hard. Washing and changing bring it down.
if me():bloodied() > 0.3 then G:Narrate("The cashier stares at your shirt.") endActor:changeSex()#Flips their presented gender and re-applies their appearance.
Actor:cloneFrom(other)#Makes this person identical to other: appearance, name, stats and vars. Returns this actor.
Actor:closeEyes(closed?)#Holds the eyes shut (true or no argument) or opens them.
Actor:copyAppearanceFrom(Other) → bool#This person now looks like Other: face, body, hair, skin and clothes. Their name, pronouns, age and tastes stay theirs, and their own look is kept (saved) for restoreAppearance(). It copies what Other really looks like, so A:copyAppearanceFrom(B) then B:copyAppearanceFrom(A) swaps two people.
Player:copyAppearanceFrom(Stranger)
Stranger:copyAppearanceFrom(Player)Actor:die(cause?, killer?) → bool#Dead, here and now: the body falls (ul_Blood wounds.json dead.activity), its pose stops after freeze_after seconds, and it stays where it is: the scene's end does not take it away and the room's life no longer moves it. A known person is dead for the world too (history, family, home), as Person:die; killer is kept as for Person:die. Never the player; false then.
p:die("bled out from a stab wound")Actor:exportAppearance() → text#Their look as .ulcharacter text (the preset grammar). Keep it under Game:setSetting to meet the same face again in another save.
local look = friend:exportAppearance()Actor:getFluids() → table#What is on them now: a list of {area, type, amount, wet}, wet going from 1 (fresh) to 0 (dried).
for _, f in ipairs(Victim:getFluids()) do
if f.area == "Face" then Game:say("...") end
endActor:getInjuries() → { {name, region, severity, daysLeft} }#The visible injuries, with how strong each is today (daysLeft -1 = for good).
Actor:getMakeupStyles(zone) → table#The style names a zone offers (every mod's Makeup/<zone>/), sorted.
local lips = Actor:getMakeupStyles("Lips")
Actor:setMakeup("Lips", lips[1], 0.6, 0.1, 0.1, 1)Actor:getMorph(name) → number#Where a shape (or dial) stands now.
if Player:getMorph("weight") > 0.5 then ... endActor:getMorphValue(morph) → number#One morph's value.
Actor:getUp() → bool#Back on their feet and out of the hurt or frightened pose: helped up, patched up. The wounds and the blood stay.
p:stopBleeding(); p:getUp()Actor:hasInjury(name?) → bool#Whether that injury (or any) still shows.
Actor:healInjury(name?) → bool#Removes one injury, or all of them without a name (a hospital visit).
Actor:importAppearance(text) → ok#Blends .ulcharacter text (from exportAppearance or a preset file) onto their current look. False when the text has no preset lines.
friend:importAppearance(Game:getSetting("mymod.friend_look"))Actor:isBleeding() → bool#Whether a wound is still bleeding.
if Victim:isBleeding() then Game:Narrate("The floor under her is wet and dark.") endActor:isDead() → bool#Killed with die() and lying where they fell.
if p:isDead() then G:Narrate("Nobody moves her.") endActor:isDown() → bool#On the floor from their wounds (ul_Blood): a wound past Reactions/wounds.json's down_at, or a leg past leg_down_at. They stay down until getUp().
if p:isDown() then G:Narrate(p:name() .. " is on the floor.") endActor:knockOut(cause, minutes?) → bool#Out cold on the floor for the cause's game minutes (Reactions/*.json unconscious.causes), or minutes. Lasts past scenes, rooms and saves; they come to when the clock passes it. False for the player, the dead, or an unknown cause without minutes.
Actor:modifyMorph(name, delta) → number#Moves a shape by delta (clamped to -1..1) and returns the new value: a month of dieting, a season at the gym.
Player:modifyMorph("muscle", 0.05)Actor:mood(name, seconds)#Puts the face recipe of a mood on the person between lines, held until the next mood or spoken line: a reaction shot with no words. Names are those of CharGen/moods.json (Neutral, Happy, Flirty, Angry, Sad, Surprised, Shocked, Scared, Furious, Crying, Pain, Evil, Embarrassed, Bored, Irritated, Hurt, Unconscious...); nil or an unknown name is Neutral. With seconds the face eases there instead of snapping.
p:mood("Shocked")Actor:pullOut() → int#Takes out everything stickIn left in them; each wound it plugged then bleeds hard. Returns how many came out.
if Victim:pullOut() > 0 then Game:Narrate("It comes out with a rush of blood.") endActor:randomizeFace()#Re-rolls their face.
Actor:randomizeHairs()#Re-rolls their hair.
Actor:randomizeRace()#Re-rolls their ethnicity, with skin and features.
Actor:randomizeSexy()#Re-rolls breasts, genitals and glutes, leaving build and face alone.
Actor:refitClothes()#Fits every worn garment again to the body as it is now, after setMorph calls (which do not refit by themselves; importAppearance and presets do).
Actor:restoreAppearance() → bool#Gives back the look this person had before copyAppearanceFrom. False when they are wearing their own.
Player:restoreAppearance()Actor:setMakeup(zone, style, r?, g?, b?, a?) → bool#Puts on (or takes off) one makeup layer: zone is Eyeshadow, Blush, Liner, Lips or Tears, style a file of Makeup/<zone>/ (getMakeupStyles), the colour 0..1 and a its strength (1; 0 or a nil style takes the zone off). Saved with the look.
Actor:setMakeup("Lips", "LK_Lips_03", 0.55, 0.1, 0.12, 0.9)
Actor:setMakeup("Liner", nil) -- offActor:setMorph(name, value) → bool#Reshapes the body or face, saved with the person. name is a shape of CharGen/MorphAliases.txt (weight, muscle, breasts, belly, butt, nose, lips...; from -1 to 1 when the shape has two sides: weight -0.6 is thin, 0.6 heavy) or a Genesis 8 dial name.
Player:setMorph("weight", 0.4)Actor:setMorphValue(morph, value)#Sets one body or face morph (0–1).
Actor:setTears(strength?, style?) → bool#Streaks of run mascara down the cheeks: strength 0..1 (1), style a file of Makeup/Tears/ (a random one when left out and none is on yet). setTears(0) dries them. Saved with the look, so wash them off when the scene is over.
Victim:setTears(0.8)
-- later
Victim:setTears(0)Actor:setWet(amount) → bool#The whole body wet, 0 (dry) to 1: sweat, a shower, rain. It dries by itself.
Player:setWet(0.8)Actor:shootAt(target) → string?#A shot from their hand that misses target, past the side of the head, ending in whatever is behind: a bullet hole in a wall, cracks in a window (pictures from <mod>/Impacts/Wall and Impacts/Glass, each name.png with its mask name_M.png). Returns "wall", "glass", or nil when it hit nothing. A shot that lands is a wound: target:addWound(bone, "front", 0.85, "Gunshot").
if Player:shootAt(Victim) == "glass" then Game:Narrate("The window behind him stars.") endActor:stickIn(bone, mesh, side?, depth?) → bool#Leaves mesh (a .glb path under a mod, "Rooms/Sets/...") stuck in the body at bone, depth cm in (6), through a stab wound: it moves with them, and the wound bleeds little while it is plugged. The blade is the mesh's longer side from its pivot.
Victim:stickIn("abdomenUpper", "Rooms/Sets/GenCore/Pieces/GenCore/Product_Knife_Kitchen.glb")Actor:stopBleeding()#Every wound stops bleeding (a dressing, a tourniquet). The blood already there stays until washed.
Victim:stopBleeding()Actor:unconsciousDepth() → number#0 to 1, how deep they are out (the cause's depth).
Actor:unconsciousMinutes() → number#Game minutes until they come to by themselves; 0 when not out.
Actor:wakeUp()#Brings someone out cold round now: up off the floor, dazed.
Actor:wash(area?) → int#Washes the fluids off one area, or off everything when area is left out, and leaves the skin wet for a while. Returns how many marks came off.
Victim:wash()Actor:washClothes() → bool#Washes what soaked into their clothes (blood from a wound), worn or put away: a laundry. False when they have no wardrobe.
Player:washClothes()Direction
Actor:alive(amount)#The face’s own life on top of the mood, 0..1: breath through the mouth, eyelids that drift, brows that lift now and then. 0 is still.
p:alive(0.5)Actor:animSpeed(rate)#The body’s clips play at rate: 0.5 half speed, 1 normal (0..4).
p:animSpeed(0.5)Actor:blink(mode)#No argument: one blink now. false stops blinking (a stare, a corpse), true resumes.
p:blink()Actor:face(weights, seconds)#A face composed from any expression morphs: { eCTRLAngry_HD = 0.6, ... }, reached over seconds (0.3 by default). Morphs held before and not named go to 0.
p:face({ eCTRLFlirting_HD = 0.7, eCTRLGlare_HD = 0.4 }, 0.5)Actor:freeze(on)#Holds the body on its current frame (true, the default) or lets it move again (false). The face and the gaze go on.
p:freeze(true)Actor:lookAt(target, options)#The neck, head and eyes turn to target and stay on it: another actor, "camera" (the lens, wherever each shot puts it), or a stage point { x, y, z } in metres from the player’s feet. options: seconds (ease, 0.35), weight (how far the head follows, 1), max (degrees the head may turn, 60), eyes = true (eyes only). lookAt() lets go.
landlord:lookAt({ 0, 0, 0.9 }, { seconds = 0.7, max = 40 }) -- his eyes drop to her hipsActor:turnTo(target)#Turns the body to face another actor, "camera" or a stage point, as the chest the clip shows faces.
p:turnTo(landlord)Actor:walkTo(position, activity) → started#Walks to the stage point { x, y } (metres from the player’s feet, the room’s axes), then plays activity (or the idle). false when no path was found.
p:walkTo({ 2.4, 0.4 }, "idle_f")Staging
Actor:animate(activity?)#Plays an activity from .ulactivity (smoke, dance, eat…); no argument returns to idle.
Actor:animate("smoke")Actor:heldClip(name, loop?) → bool#Plays a clip of the rigged thing this person holds (a whip's Crack, a belt's Swing; Hang loops by itself from the pick-up). loop defaults to false. false when they hold nothing rigged or it has no such clip; the clip names are in the piece's .ulmat rig.
Actor:pickUp("Product_Whip_Bull_Black")
Actor:heldClip("Crack")Actor:hide()#Takes them out of the scene.
Actor:Interaction(name, other)#Touches, holds or kisses other on the spot: looks, goes to the right place (a step in, round to their side or back, crouched or kneeling), puts a hand or the lips on their skin almost anywhere on the body, whoever they are, then lets go. name is a .ulinteract file in any mod's Interactions/ (see Touches). Returns false (reason in the log) when the touch is unknown or out of reach from anywhere nearby: walk closer first with moveToPerson. Also spelled interaction.
Actor:IsHolding()#true while this person carries something picked up with pickUp. Also spelled isHolding.
Actor:isSpeaking()#True while a clip from speak (or a line's silent mouth track) is playing.
while a:isSpeaking() do endActor:moveToPerson(other)#Walks up to other and faces them.
Actor:moveToPersonStand(other, cm)#Walks to that distance from other (0 = their spot).
Actor:PickUp(name)#Picks up the nearest handheld thing whose name contains name ("Coffee_Mug", "Smartphone", "Book": the pieces a room set's catalog.ulset marks handheld), within 3 m: walks, crouches and reaches as a touch does, closes the hand round it and carries it in front of the body until putDown. Returns false (reason in the log) when nothing of that name is near, it is too big for one hand, or it cannot be reached. Also spelled pickUp.
Actor:PutDown([item [, where]])#Without an item: puts what this person carries back where it was taken from; false when they carry nothing. With an item id of their inventory that has a room piece (an .ulitem Piece:, or a piece: object taken from a room): puts one down near them, on the nearest surface whose piece name contains where ("Desk"), else any surface in reach, else the floor, and returns the new prop's key (nil when it could not). It stays there, saved with the game. Also spelled putDown.
Actor:putDown("radio_portable", "Desk")Actor:show()#Puts them in the scene.
Actor:speak(file)#Plays a sound file from this person's mouth, lips moving to it. file is a path under any mod's Audio/ folder (later mods win) or an absolute path. Returns false when no mod has the file. A second call replaces the first.
Actor:speak("Voice/scream_01.wav")Actor:spray(type, strength?, target?, area?, from?) → bool#A jet of type (a fluid of Fluids/fluids.json with a jet block) from their body: from is Penis, Vagina or Mouth (the crotch when left out). With a target, aimed at its area (Face by default); a penis is aimed by raising it, not by bending the stream. Where it lands it marks people and leaves puddles that dry on anything else. strength scales the speed (1).
Him:spray("Semen", 1, Victim, "Face", "Penis")Actor:StopInteraction()#Lets go of whatever this person is touching (a touch with "hold": -1 waits for this). Also spelled stopInteraction.
Actor:stopSpeaking()#Cuts the clip started by speak and relaxes the mouth.
Actor:take(prop)#A prop of the room (an entry of Room:props(), or its key) goes into this person's inventory, wherever they stand, and is gone from the room for good (a venue restocks after restock_days). Returns the item id, nil when there is no such prop. Raises propTaken when it was not theirs.
local item = Player:take(Room:props("Radio")[1])Actor:thought(text, seconds?)#A thought bubble over their head: a pale cloud with a trail to the head, so it reads as what they have on their mind, not as speech. It follows them while the camera moves and fades out after seconds (default from the length, 4 to 9). Returns false when they are not on screen, so you can say it another way (a message). A new thought replaces theirs.
if not Friend:thought("Did I leave the oven on?") then Game:ShowMessage(Friend:name() .. " looks distracted.", 5) endWhereabouts
Actor:addScheduleEntry(fromHour, toHour, weekdays, venueTag)#Adds a rule to their weekly schedule. weekdays is a bitmask: bit 0 = Sunday, 127 = every day. First matching rule wins.
Actor:addScheduleEntry(18, 23, 127, "gym")Actor:addToPeopleHere()#Keeps them at the player's location after the scene.
Actor:assignWhat() → text#What they are doing there ("having dinner").
Actor:assignWhere() → text#Where Game:AssignResidents() put this family member ("kitchen").
Actor:clearSchedule()#Removes all their schedule rules.
Actor:getBuilding("Home" | "Work" | "Current") → text#A venue tag.
Actor:getScheduledLocation(hour, weekday) → text#Where their schedule puts them at that time.
Actor:isAt("Home" | "Work") → boolean#Whether they are there right now.
Actor:setCurrentLocation(venueTag)#Moves them to a place.
Actor:setUntil(hoursElapsed)#Legacy: stay put until that hour. Stored but not used by the routine scheduler yet.
Jobs
Actor:addCriminal()#Joins organised crime.
Actor:addEmployee(salary?)#Hired at the player's business (the building the player is in).
Actor:addProstitute()#Starts sex work (+5 pornfame).
Actor:getJob() → text#Their job title.
Actor:isJob(title) → boolean#Has that job title.
Actor:isProstitute() → boolean#Does sex work.
Actor:modifySalary(multiplier)#Multiplies an employee's salary.
Actor:removeEmployee()#Fired from it.
Actor:removeProstitute()#Stops sex work (pornfame back to 0).
Actor:setCrimeBoss()#Becomes the player's crime boss.
Actor:setDifferentMajor()#Studies another major.
Actor:setJob(title)#Sets a free-text job title.
Actor:setSameMajor()#Studies the player's major.
Actor:setSubject()#Lectures the next subject of the player's major.
Actor:setWorkHere()#They now work at the building the player is in.
Items
Actor:addItem(id, count?, { name, category, value, description, mod }?)#Gives them count (default 1) of an object and returns how many they now have. An id with an .ulitem takes its name, category and worth from it; any other id is described by the table, the first time a mod passes one (the engine remembers that description for the next time the id is handed out). value is the worth of one in dollars and re-appraises the ones they already have.
Actor:countItem(id)#How many of that object they own, 0 when none.
Actor:getItems()#Everything they own: a list of { id, name, count, value, category, description, mod }. The player's list is also shown in the wallet.
Actor:giveItem(Other, id, count?)#Hands count (default 1) to another person, with its name and worth. All or nothing: false when they have fewer than that.
Actor:hasItem(id, count?)#Whether they own at least count (default 1).
Actor:itemsValue()#What everything they own is worth: the sum of count × value.
Actor:removeItem(id, count?)#Takes up to count (default 1) away and returns how many were actually removed (0 when they had none).
Actor:setItemValue(id, dollars)#A new worth for one of their objects: appraised, damaged, aged.
Pregnancy
Actor:countPregnancyDays() → number#Days of pregnancy.
Actor:endPregnancy()#Ends the pregnancy.
Actor:getBabyDaddy() → person#Who got them pregnant; nil if not pregnant or not in the world.
Actor:getPregnancyTag() → text#How it started (consensual or not).
Actor:impregnate()#Starts a pregnancy, no roll.
Actor:isOnPeriod() → boolean#Always false for people (the legacy game had no cycle for them).
Actor:isPregnant() → boolean#Pregnant.
Actor:setWantsBabies(on)#Whether they want children.
Actor:wantsBabies() → boolean#Wants children.
Sex
Actor:clearBondage()#Removes their bondage.
Actor:getSexPain() → number#Pain in the current sex scene, 0 to 100, starting at 0. Rises slowly while resistance is high and the pace is wrong; at 100 the actor passes out.
Actor:getSexResistance() → number#How much this actor fights the current sex scene, 0 to 100. 100 when forced (a climax takes a little off); a willing partner starts at 0 and it rises when the pace or the pose is wrong for them. 0 outside a scene.
Actor:getTagIfRape() → text#Aggressive, AggressiveFM or empty: the tag to filter a non-consensual scene with.
Actor:isDeflowered() → boolean#The player took theirs.
Actor:isDeflowerer() → boolean#They took the player's virginity.
Actor:isForcedParticipant() → boolean#Marked as non-consenting.
Actor:isUnconscious() → boolean#Passed out from pain in the current sex scene. The scene goes on; it lasts until the scene ends.
Actor:isVirgin() → boolean#Nobody has taken their virginity.
Actor:setForcedParticipant(on)#Marks them as non-consenting in the running sex scene.
Actor:setVirgin()#Makes them a virgin again.
Lifetime
Actor:delete()#Removes them from the scene (a known person still exists).
Actor:deletePerson()#Erases them from the game for good.
Actor:generatePersonMatchRace() → person#A new permanent person of this person's ethnicity.
Also callable as generateRelativeMatchRace.
Actor:generatePersonTemporaryMatchRace() → person#A new temporary person of this person's ethnicity.
Actor:isTemporary() → boolean#Generated and not (yet) kept.
Actor:makePermanent()#Keeps a generated person: they join the people the player knows and are saved.
Also callable as setPermanent.
Actor:saveAndDelete()#makePermanent() then delete().
Input
Actor:enterCustom(key) → text#Waits for the player to type a text, stores it in this person's variable key (read it with getVar(key)) and returns it.
Actor:enterFirstName() → text#Waits for the player to type a first name for this person, sets it and returns it.
Dependents
Actor:addDependent({ name, relation, gender, birth | age, mod, ... }) → id#Someone this person is responsible for who is never drawn: a child, a ward, a frail parent. Listed under In your care with the player's contacts, with their age. age (years) or birth (game hours, negative = before the game) sets when they were born; any other field (school, stage...) is kept as text for your mod. Returns its id, nil without a name. Saved.
local id = Player:addDependent({ name = "Mia", relation = "daughter", gender = "female", age = 7, mod = M })Actor:getDependents() → table#Everyone in their care: { { id, name, relation, gender, age, birth, mod, ...your fields } }. age follows the calendar from birth.
for _, d in ipairs(Player:getDependents()) do ... endActor:removeDependent(id) → bool#They are no longer in this person's care (grown up and gone, adopted away). false for an unknown id.
Player:removeDependent(id)Actor:setDependent(id, key, value) → bool#Changes one field: name, relation, gender, birth, age (moves the birth date), or one of your own (nil removes it). false for an unknown id.
Player:setDependent(id, "stage", "teenager")Driving
Actor:canDrive(kind?) → bool#A licence and a motor vehicle (of that kind): what a road trip or a delivery job should check. A bicycle does not count.
if Player:canDrive() then ... endActor:getVehicles() → table#Their vehicles: { { id, name, kind, value, count } }.
for _, v in ipairs(Player:getVehicles()) do ... endActor:hasDrivingLicence() → bool#Whether they hold the driving licence: the qualification ul_Base/driving_licence (or, for older mods, the stat driving_licence above 0.5). Also spelled hasDrivingLicense.
if not Player:hasDrivingLicence() then return false endAlso callable as hasDrivingLicense.
Actor:ownsVehicle(kind?) → bool#Whether they own a vehicle: an inventory item of category Vehicle, of that kind ("car", "van", "motorbike", "scooter", "bicycle"; nil = any). The kind is the .ulitem's Kind, else the last _ part of the id (my_estate_car is a car). The legacy stat car_value above 0 counts as a car.
Player:ownsVehicle("van")Actor:setDrivingLicence(bool) → bool#Grants or suspends the licence, whichever mod runs the test or the court case. Keeps the driving_licence stat in step for older mods.
Player:setDrivingLicence(true)Lasting conditions
Actor:actor:confine(conditionId [, place [, cause]]) → bool#Shuts the person in: adds a condition that has "confines": true (Conditions/*.ulconditions) with a place a mod reads back. An NPC holder does nothing until released; the player's actions test the var confined. With starve_days the holder dies of starve_cause unless feed() is called in time.
a:confine('locked_in', 'cellar')Actor:actor:confined() → { condition, place, since } | nil#The confining condition the person holds, with its place and the game hour it began.
local c = a:confined()Actor:actor:feed() → bool#Someone brought food and water: restarts the starve_days of every confining condition.
a:feed()Clothing
Actor:damageClothing(slot, holes?, rips?, replace?) → bool#Holes and rips through what they wear in slot, 0..1 each (1 = in tatters). Wear only grows: a second, smaller tear changes nothing unless replace is true. The same garment keeps the same holes; saved with their wardrobe. false when nothing is worn there.
Victim:damageClothing("Top", 0.2, 0.6)Actor:getClothingDamage(slot) → table#{ holes, rips } of what they wear in slot (both 0 when intact), or nil when nothing is worn there.
local wear = Player:getClothingDamage("Bottom")
if wear and wear.rips > 0.5 then Game:Narrate("Your jeans hang in strips.") endActor:getClothingPattern(slot) → { id, color1, color2, size } | nil#The pattern on what they wear in slot, colours as "#RRGGBB"; nil when it wears none.
local p = Actor:getClothingPattern("Top")
if p and p.id == "Monogram" then Game:print("Fancy.") endActor:getClothingState(slot) → string|nil#The worn state of what is in slot ("worn", "aside", "lowered", "thigh", "knee", "ankle", or their -one forms), nil when the slot is empty.
if Actor:getClothingState("Bottom_Under") ~= "worn" then ... endActor:getEquippedItem(slot) → table#What they wear in a slot (same names as isEquipped): { id, name, rarity, stats = { stat = change } } from its .ulcloth, or nil. A dress answers for both Top and Bottom.
local top = Player:getEquippedItem("Top")
if top and top.rarity == "legendary" then ... endActor:repairClothing(slot) → bool#Mends what they wear in slot completely.
Player:repairClothing("Top")Actor:setClothingPattern(slot, pattern, color1?, color2?, size?) → bool#Puts a pattern (a Patterns/*.ulpattern id) over what they wear in slot. Colours are "#RRGGBB", by default the pattern's own; size multiplies its Scale. nil takes the pattern off. Saved with their wardrobe. false when nothing is worn there, the id is unknown, or the pattern is refused (a cutout on someone under 18).
Actor:setClothingPattern("Bottom", "Leopard")
Actor:setClothingPattern("Top", "Monogram", "#111111", "#D4AF37", 1.6)Actor:setClothingState(slot, state) → bool#Puts what they wear in slot into a worn state: "worn" (as dressed), a key of the garment's Worn cut group ("aside", "lowered", "lifted" for a skirt or dress hiked up, with its shortest Length cut standing in when it has no Lifted key) or a garment declared StateOf: it (the base game's panties: "thigh", "knee", "ankle" stretched between both legs, "thigh-one", "knee-one", "ankle-one" hanging on one leg). Works whatever panty they wear; the tint and pattern follow. false when nothing is worn there or it has no such state.
Actor:setClothingState("Bottom_Under", "aside")
Actor:setClothingState("Bottom_Under", "ankle")
Actor:setClothingState("Bottom_Under", "worn")Other
Actor:getExposure()#Not documented yet. Developer note: getExposure(): { breasts, genitals, butt, any = bool, sexiness = 1-5 } -- what shows through what they wear (UClothingComponent::GetBodyExposure); nil for a creature or someone with no wardrobe. isExposed(part?) is one flag ("breasts", "genitals", "butt"; no part: any).
Actor:isExposed(part)#Not documented yet. Developer note: none