Reference

Game API

Every function of the Game object (ModGame in libraries and UI scripts).

Game is the scene API: it is passed to every scene's RUN, and is the global ModGame in libraries and UI scripts. Function names are not case-sensitive. The list below is generated from the game's own bindings, so it is always complete; functions without a description yet show the developer's note instead.

254/254 documented

Scene flow

Game:clearAllTimeouts(prefix?)#

Lifts every cooldown whose id starts with prefix; with no prefix, all of them. Returns how many. Meant for test tools that replay an event.

Game:clearAllTimeouts("ynl_")
Game:clearTimeout(id)#

Lifts a cooldown set by timeout at once. Returns how many were lifted (0 or 1).

Game:clearTimeout("ynl_bouncer")
Game:followUp(sceneName)#

Queues a scene to run when the next action completes, before anything else.

Game:followUp("ynl_heist_part2")
Game:ForcedTrigger() → boolean#

True when the scene was started on purpose (an action's SCENE_ALWAYS, or followUp) rather than by the random roll.

Game:GetBuiltin(name) → number#

A built-in value: HoursElapsed, TimePassed (hours since this scene started), WHEN (hour of day), Difficulty, CostOfLiving, SexualFreedom. Unknown names return 0.

Game:GetCurrentAction() → text#

The action that started this scene ("socialize"), or "" when the scene was started another way (a follow-up, the journal, a timer). Lets one scene listed under several actions in WHAT tell them apart: if Game:GetCurrentAction() == "socialize" then.

Game:getLastErrors()#

The latest scene errors of this session (at most 50, oldest first), as rows { scene, message, hours }. An error that happens in a scene does not show on screen; this lets a test page list them.

Game:isNpcSimulation()#

True inside an NPC scene (the autonomous town), false in the player's. For the rare branch that must differ, such as dressing a newly generated actor only in the player's scene.

Game:isTimingOut(id) → boolean#

True while that cooldown is running.

Game:queueScene(sceneId, person?)#

Runs the scene as soon as nothing is on screen and no menu is open, instead of after the next action like followUp. For consequences an Events callback raises. With person, that person is the queued scene's Actor, as if the player had picked the interaction on them; someone this scene drew is kept for it. Waiting scenes are kept in saves.

Game:queueScene("ul_ar_pull_knife", Actor)
Game:rollScenes(what)#

Once this scene is over, rolls the scenes whose WHAT lists what, as if an action of that id had just finished here; each scene's own odds and gates still apply. An action with SCENE_ALWAYS skips the usual roll, so a scene that asks a question first (which drink?) calls rollScenes("drink_coffee") to keep that drink's moments.

Game:SceneEnd()#

Ends the scene and clears scene-scoped settings (blockPregnancy, filters, PreciseModify).

Game:sceneEndLoadLastSave()#

Legacy: end the scene and reload the last save. The reload is not implemented yet; it behaves like SceneEnd().

Game:SceneStart()#

Marks the start of the visible part of a scene. Pair it with SceneEnd().

Game:timeout(hours, id)#

Starts a cooldown. A scene whose name is on cooldown is skipped by the random roll; an action id is not offered. Scaled by the player's scene-frequency setting.

Game:timeout(24, "ynl_bouncer")

Also callable as timeoutPrecise.

Dialogue

Game:fillText(text) → string#

Fills the <Name.token> tokens of a text the way Say and Narrate do, for text that is not a line: a notification, a panel, a log entry.

Notify:send("mymod", "keys", { title = Game:fillText("<Partner.name> left <Partner.his> keys.") })
Game:Narrate(text)#

A line of narration, written in the first person. Waits for the player to advance.

Game:Narrate("The rain has not stopped all day.")
Game:prerenderVoice(speaker, mood, text)#

Renders the line's voice into the cache now, without playing it, so a scene whose lines are known in advance (a cinematic, a trailer, a mod's own fillers) never waits on the speech model. speaker nil is the narrator. The speaker, mood and text must be exactly what Say or Narrate will use: the cache key is the voice, the mood's instruction and the text. Cache renders queue one at a time behind live lines and never hold or cancel them. Does nothing without a voice mod or with voices off.

Game:prerenderVoice(landlord, "Angry", "Friday. Not next Friday. This one.")
Game:Say(person, mood, text)#

A spoken line with the person's name and portrait; their face takes the mood (Happy, Flirty, Angry, Sad…, or nil). Waits for the player.

Game:Say(Actor, "Happy", "You came!")
Game:secondScreen(person?)#

Puts a person "on the phone": their lines keep their portrait but they are not placed in the room. No argument ends it for everyone.

Game:secondScreenIfHidden(person)#

Like secondScreen, but only if the person is not already visible in the room.

Game:ShowMessage(text, seconds?)#

Shows a short on-screen message that does not wait (default 5 seconds). Works from libraries and UI scripts too.

Game:showPanel(title, build) → value#

Opens a card over the scene and waits. build(UI, root, close) fills it with the UI builder; calling close(value) (from a button) closes it and showPanel returns that value. The card's X returns nil. UI is also a global while the card is up.

local pick = Game:showPanel("Phone", function(UI, root, close)
	UI:CreateText(root, "Three new messages.")
	UI:OnClick(UI:CreateButton(root, "Call Mum"), function() close("mum") end)
end)
Game:voicePrerenderPending()#

How many lines queued by prerenderVoice are still to render (queued plus the one in flight). 0 when the cache is warm; a scene may Hold until then.

while Game:voicePrerenderPending() > 0 do Game:Hold(1) end

Choices and input

Game:Choice(index, condition, text, options?)#

Registers an option for the next GetChoice(). index is what GetChoice returns; condition is nil or true/false, and a false option is not shown. options: reason (a false option is shown greyed with this reason instead of hidden), tooltip (hover text), odds (0.6 or 60: printed as "(60%)").

Game:Choice(1, Player:getStat("money") >= 20, "Buy a round", { reason = "Needs 20" })
Game:chooseContact()#

Legacy name for selectNPC; read the pick with getSpecific("chooseContact").

Game:chooseMajor()#

Offers the university majors as choices. Must be followed by setMajor().

Game:enterBusinessName() → text#

Waits for the player to type the name of the business they are in, and returns it.

Game:GetChoice() → number#

Shows the registered options, waits, and returns the index of the pick. Called again with no new options, returns the same answer.

Game:getSelectedNPC() → person#

The contact picked with selectNPC; an invalid person for "Nobody".

Game:selectNPC(tag?)#

Lets the player pick one of their contacts (or "Nobody"). Read the pick with getSelectedNPC().

Game:setMajor()#

Waits for the pick offered by chooseMajor() and makes it the player's major.

Staging

Game:AnimatePair(a, b, tag)#

Plays a paired animation with that tag (a kiss, a hug) without starting a sex scene.

Game:AnimatePair(Player, Actor, "Kissing")
Game:ClearExtras()#

Sends off the people Extras brought, now.

Game:ClearStage()#

Puts every staged person back (collision, gravity, movement) and destroys the props and lights. SceneStart and SceneEnd call it for you; call it yourself between two set-ups in one scene.

Game:ClearStage()
Game:dressFormal()#

Dresses the player in the formal uniform of Clothes/Outfits/uniforms.txt (evening wear, a suit).

Game:Extras(count, activity) → added#

Fills the room with count people of the venue’s own kind (4 by default), all doing activity when given ("dance", "drink"...). They go with ClearStage and the scene’s end. Returns how many came.

Game:Extras(8, "dance")
Game:faceEachOther(a, b)#

Turns two people towards each other.

Game:Piece(match) → table or nil#

A furniture piece of the room in the stage frame: { x, y, z, yaw, w, d, h } in metres from the player’s feet and degrees, or nil. The match is on the piece’s kind, type, category or id ("TV", "Sofa"); the first match wins. To stage someone beside a piece.

local tv = Game:Piece("TV"); Game:StageActor(Player, { tv.x + 2.2, tv.y, 0 }, tv.yaw + 180)
Game:PlayAnimation(person, clip, loop)#

Plays one animation file of your mod on one person: an .ulanim or .ulpose from the posing editor (a role of an exported scene works too) or a Daz .fbx, relative to Animations/. loop defaults to true. End it with StopScene.

Game:PlayAnimation(Actor, "Hug_Giver.ulanim", true)
Game:PlayScene(name, a, b, …)#

Plays a scene made in the posing editor and exported into a mod (Animations/<name>.ulposescene): up to six people, given in any order, are cast into its roles by what each role requires (anatomy, never gender), placed around the first role, and animated in step. Returns false when the scene is missing or nobody fits a role (the reason is in the log). Not for sex: use Sex.

Game:PlayScene("Hug", Player, Actor)
Game:StageActor(person, position, facing) -> ok#

Puts a person on a mark: position is {x, y, z} in metres in the stage frame (the player's feet, the room's yaw), facing the yaw in degrees their face should point to, or nil to leave it. The mark is immediate: a person still walking to someone when the camera starts would otherwise be a floor away. Collision and gravity are off while staged and come back at SceneEnd or ClearStage. False when the handle is not a person or there is no player yet.

Game:StageActor(landlord, {1.2, 0.4, 0}, 180)
Game:StageLight(settings)#

A point light for the shot: position in metres in the stage frame, intensity in lumens (default 6000), color {r, g, b}. No shadows, 14 m reach. Removed at SceneEnd or ClearStage.

Game:StageLight({ position = {0.6, -0.8, 2.2}, intensity = 2500, color = {1, 0.85, 0.7} })
Game:StageProp(shape, settings) -> ok#

Spawns a practical: shape is "cube", "cylinder" or "sphere"; settings takes position and rotation ({x, y, z}, metres and degrees in the stage frame), size (scale, 1 = one metre), color ({r, g, b}, linear). With person (and an optional socket name) the prop is attached to that person instead and position/rotation are relative to the socket. Props have no collision and are destroyed at SceneEnd or ClearStage.

Game:StageProp("cylinder", { person = cop, socket = "rHand", position = {0, 0, 0.1}, size = {0.03, 0.03, 0.4}, color = {0.05, 0.05, 0.05} })
Game:StopScene(person)#

Ends the scene or clip person is in; everyone in it goes back to the animation they had before. A scene that does not loop ends by itself.

Game:StopScene(Actor)

Cinematics

Game:Caption(text, style, seconds)#

A third text placed anywhere: style = { x = 0.08, y = 0.9, size = 22, color = { r, g, b } } as fractions of the screen; left-aligned on the left third, right-aligned on the right. 0 seconds keeps it until the next call; an empty text clears it.

Game:Caption("Rent: $410 due Friday", { x = 0.08, y = 0.9 }, 3)
Game:Duck(level, seconds)#

The music’s volume multiplied by level (0..1), reached over seconds (0.4); 1 brings it back. Under a spoken line.

Game:Duck(0.35, 0.3)
Game:EndCutscene()#

Hands the camera back to the game after a shot played with wait = false. A scene that ends or errors under a shot does this by itself.

Game:Fade(seconds, toBlack, color)#

A fade over seconds: toBlack = true to black (or to color { r, g, b } when given), false back to the picture.

Game:Fade(0.5, true, { 1, 1, 1 })  -- to white
Game:Flash(color, seconds)#

A hit of color { r, g, b } (white by default) that clears over seconds (0.3): a camera flash, a blow.

Game:Flash({ 1, 1, 1 }, 0.25)
Game:Freeze(seconds)#

The world stands still for seconds of real time (bodies, cloth, particles); the camera, the words and the music go on. A narration over a frozen frame.

Game:Freeze(2)
Game:Grade(nameOrTable, seconds)#

The picture’s grade, reached over seconds (0.5): a mod’s Grades/<name>.ulgrade by name, or a table with tint { r, g, b }, saturation, contrast, gamma, vignette, grain, bloom, chroma (chromatic aberration), blur (0..1, the whole frame out of focus), exposure (stops), temperature (Kelvin). nil goes back to the plain picture. Given back when the scene ends.

Game:Grade("drugged", 2.5)
Game:HideHud(on)#

Cinema mode: hides every HUD widget except the dialogue box and the choice menu; false brings them back. A cutscene does this by itself.

Game:HideHud(true)
Game:Hold(seconds)#

The script waits that long; the camera, the bars and the text stay as they are.

Game:Hold(2.5)
Game:Letterbox(on)#

Shows or hides the cinematic black bars. A cutscene file sets its own with letterbox.

Game:Marker(name)#

A named point in the script. Free when the scene plays; the live director jumps to it (cine.run scene@name: no waits until the marker, then the scene plays) and the recording’s timeline.json lists when it passed.

Game:Marker("hands")
Game:Music(cue)#

Crossfades the music to that .ulaudio cue; the cue already playing changes nothing; "" fades the music out.

Game:Music("Music.Venue.stripclub")
Game:PlayCue(cueId)#

Plays an audio cue by id from any mod's audio definitions (see Game audio), as a one-shot. Nothing happens, with a log line, when no mod defines the id.

Game:PlayCue("door_slam")
Game:PlayCutscene(id, roles, wait) → played#

Plays Cutscenes/<id>.ulcutscene from your mod with the camera, the script waiting until the last shot ends. roles names the people the shots anchor on (player is implied). wait = false leaves the camera on the last shot for the lines that follow, until EndCutscene. Returns false without pausing when there was nothing to play. See Cinematics.

Game:PlayCutscene("uls1_funeral_arrival", { friend = Cast.get("friend") })
Game:Sfx(cueOrFile, settings)#

One sound: a cue by id, or a loose file (absolute, or under any mod’s Audio/). settings = { at = actor, volume = 1 } plays it from that person’s head.

Game:Sfx("Effects/door_slam.ogg", { at = landlord })
Game:Shot(shot, wait) → played#

One camera shot inline, the same keys as a shot in a cutscene file plus roles. Waits for its duration unless wait = false, which holds the shot under the dialogue until EndCutscene.

Game:Shot({ frame = "person:boss", from = {1.2, 0.3, 1.6}, look_at = "face", fov = 35, roles = { boss = boss } }, false)
Game:Strobe(hz, seconds, color)#

Flashes at hz (8) for seconds (2), in color (white). 0 seconds stops a strobe.

Game:Strobe(10, 1.5, { 1, 0.3, 0.4 })
Game:Subtitle(text, seconds)#

A line drawn along the bottom of the screen by the game, for captured footage; no dialogue box. seconds = 0 keeps it until the next call, an empty text clears it.

Game:Subtitle("Nobody told her the rent was due.", 4)
Game:Title(title, sub, seconds)#

A title card in the middle of the screen with an optional line under it. seconds = 0 keeps it until the next call.

Game:Title("UNDERLIVES", "Life Has No Rules", 3)
Game:TitleStyle(style)#

How the next title cards look: { size = 64, color = { r, g, b }, y = 0.5 } (y 0 top .. 1 bottom). A gameplay insert’s label is small and low; the film’s title large in the middle.

Game:TitleStyle({ size = 28, y = 0.86 })
Game:VenueLights(settings)#

The room’s own lights (not the scene’s StageLight practicals): { scale = 0.2, color = { r, g, b }, flicker = 0 } scales and tints them; flicker 0..1 makes them unsteady. { scale = 1 } gives them back; so does the scene’s end.

Game:VenueLights({ scale = 0.12, color = { 1, 0.45, 0.55 } })

People

Game:AssignResidents()#

Decides what each family member living with the player is doing right now. Read with getAssignee(where) and Actor:assignWhere() / assignWhat().

Game:conversationSize()#

How many are in that conversation, the player included: what an action's CONVERSATION = { MIN, MAX } counts. Talking to one of two people chatting is 3.

Game:generateCreatureTemporary(species?) → person#

Creates a creature for this scene only (not kept). species is "Dog", "Horse" or "Tentacles", in any case; nil gives a dog. Creatures come from Creatures/*.ulcreature files in enabled mods (the ul_Creatures module ships them); with none loaded this returns an invalid person, so check isValid().

Actor2 = Game:generateCreatureTemporary("Dog")
Game:generatePerson(isMale, presets?) → person#

Creates a permanent person, known to the player and saved. presets is a comma-separated list of character presets. Pass the gender explicitly (the one-argument legacy form is misread today).

local p = Game:generatePerson(false, "age_groups/twenties")
Game:generatePersonTemporary(isMale, presets?) → person#

Creates someone for this scene only (not saved, not a known person). Same arguments as generatePerson.

Game:getAnyRelative(type?) → person#

Same as getRelative.

Game:getAssignee(where) → person#

The family member AssignResidents put in that part of the home ("kitchen"…).

Game:getCompanion() → person#

Who the player is with right now (their date or companion); invalid if nobody.

Game:getCompanionAny() → person#

The companion, human or not. Same as getCompanion while creatures are not in the game.

Game:getCompanionCreature() → person#

The creature that is the player's companion, placed next to the player, or an invalid person if there is none. Creatures come from Creatures/*.ulcreature files in enabled mods (the ul_Creatures module ships them); with none loaded this returns an invalid person, so check isValid().

Game:getConversation()#

The people the player talks with by talking to the scene's target: the target, whoever the target was talking with, and anyone the player already stands with. The player is not in the list. See Actions, Conversations.

Game:getCreature() → person#

A creature for this scene: the companion creature first, else a known creature this scene has not taken yet, else a new one that is kept as known. Each call in one scene returns a different creature. Creatures come from Creatures/*.ulcreature files in enabled mods (the ul_Creatures module ships them); with none loaded this returns an invalid person, so check isValid().

local dog = Game:getCreature()
if not dog:isValid() then return false end
Game:GetInvalidActor() → person#

A person handle wrapping nobody, on which every method is harmless. Useful to initialise variables.

Game:getParty()#

Everyone with the player, as a list (someone not on screen comes back as a Person handle). getCompanion() is the first of them.

Game:getPeopleHere(permanentOnly?)#

Every person where the player is, as a list. true keeps known people only, false strangers only. Someone standing in the room with the player counts as here whatever their routine says.

Game:getPerson(tag?) → person#

With a tag: the person marked with Actor:setActorVar(tag, true). Without: a random known person. nil if nobody matches.

Game:getPersonById(id)#

That known person as an Actor in this scene, brought on screen like getPerson(tag). Takes an id or a Person handle (People:, Places:residence().owner): a Person handle only has :actor() while their body is already in the room. An invalid Actor when nobody known has that id.

local owner = Game:getPersonById(Places:residence().owner)
Game:getPersonHere(permanent?) → person#

Someone at the player's location: nil = anyone, true = known people only, false = strangers only. Someone standing in the room with the player counts as here whatever their routine says.

Game:GetPlayer() → person#

The player. Scenes also receive it as Player.

Game:getRelatedPeople(type1, type2?, type3?) → list#

People who share one of these relationships with each other (a couple, siblings). Always a table, possibly empty.

Game:getRelative(type?) → person#

A random relative of the player: Parent, Child, Sibling, GrandParent, GrandChild, Cousin, or nil for any.

Game:getRelativeExcept(type1, type2?, type3?) → person#

A relative who is none of the listed types; nil if there is none.

Game:getSpecific(role, extra?) → person#

Someone with that relationship to the player: Dating, Spouse, Ex, Boss, Colleague, Neighbour, Landlord, Companion, Lecturer, Employee, PassedOn, a job title, a numeric id… Brought into the world with their saved look if needed.

local boss = Game:getSpecific("Boss")
Game:getTarget() → person#

The person the player clicked to start this interaction (the same as Actor).

Game:isWithCompanion() → boolean#

True when the player has a companion with them.

Game:isWithCompanionCreature() → boolean#

True when the player has a creature companion (getCompanionCreature() would return a valid one).

Game:joinConversation(person?)#

The player steps into person's conversation (the target when none is given): everyone in it stays where they are and turns to the player, and a scene the room was playing with them ends. Returns how many are in it now.

Game:leaveConversation()#

The player leaves the conversation; the others go back to room life, still talking among themselves. Walking a few metres away does the same.

Game:setRaceGenerated(ethnicity)#

Everyone generated later in this scene gets this ethnicity: arab, asian, black, indian, latin, white.

Relationships

Game:addNpcRelationship(type, a, b)#

Sets a family relationship between two NPCs: ParentChild, Siblings, Cousins, GrandParentChild.

Game:blockContact(person)#

Removes the person from the player's contacts and prevents them from being added again.

Game:Divorce()#

Ends the player's marriage, not only the relationship loseDating() ends.

Game:endDate()#

Everyone with the player goes their own way (the whole party).

Game:exchangeContact(person)#

Adds the person to the player's contacts.

Game:forgiveAffairs()#

Clears every affair the player has had in the current relationship.

Game:getMarried()#

Marries the player to their current partner.

Game:isPlayerMarried() → boolean#

True when the player has a spouse.

Game:loseDating()#

Breaks up with the partner chosen by Actor:setDatingId(), or with the current partner.

Game:losePT()#

The player fires their personal trainer.

Game:OpenRelationship() → boolean#

True when the player's relationship is open.

Game:removeNpcRelationship(a, b, c?, d?)#

Removes every NPC-to-NPC relationship among the given people.

Game:startOpenRelationship()#

Makes the player's relationship open.

Story state

Game:clearGlobal(name)#

Deletes a global (it reads 0 again).

Game:convertToLocalCurrency(amount) → text#

Formats a dollar amount in the current city's currency, symbol included.

Game:generateBuildingAlias(alias, venueTag)#

Picks a building of that venue type and publishes it as a global named alias, with objective methods (see the Building API).

Game:generateBuildingAlias("YnlClub", "nightclub")
Game:getActorAlias(alias) → person#

The person remembered under that name; nil if never set or not in the world right now.

Game:getGlobal(name) → number|text#

A stored global: the text when one was stored, else the number; 0 if never set.

Game:getPlayMode() → id#

The game mode this life was started in: "sandbox", "story" or a mod's own id from PlayModes/*.json. A save from before modes, or whose mode's mod is gone, reads as "sandbox". Branch a newGame handler on it to start a story.

Game:getSetting(key, default) → value#

A setting stored with setSetting, as the number, boolean or text it was; default when never set.

Game:setActorAlias(alias, person)#

Remembers a person under a name, readable from any later scene with getActorAlias.

Game:setGlobal(name, number|text|boolean|nil)#

Stores a number or a text in the save, readable from any scene. true/false become 1/0, nil clears it, and a number written as text ("5") stays a number.

Game:setGlobal("ynl_stage", 2)
Game:setSetting(key, value)#

A setting that outlives the save: kept across every game in Saved/ModSettings.json. nil forgets it. Prefix the key with your mod's name.

Time

Game:FormatDate(hours?, short?) → text#

"10 August 2026", or "10 Aug 2026" when short is true.

Game:GetDate(hours?) → table#

The date at a moment (nil = now): { day, month, year, weekday, dayOfYear, season, hour, minute, text }, weekday 0 = Sunday, dayOfYear 1-366, season "winter"/"spring"/"summer"/"autumn" in the current city's hemisphere. Negative hours reach before the game started.

Game:getHoursPassed() → number#

Game hours since day 0. Store it and subtract later to measure durations.

Game:getSeason() → string#

"winter", "spring", "summer" or "autumn" now: meteorological seasons by month, swapped for a city with Hemisphere: south.

Game:getTemperature() → number#

Degrees Celsius now: the climate's range for the season (coldest around 4:00, warmest around 16:00), the weather's offset and the day's variation. Snow keeps it at 1°C or below.

Game:getWeather() → table#

The weather now: { id, name, icon, mood, energy, outdoor, temperature, season, forced, cloud, fog, rain, snow, wind }. id is a type from Weather/*.ulweather (ul_Base: clear, partly_cloudy, overcast, fog, rain, storm, snow, heatwave, windy); temperature is in Celsius; forced is true while a scene's setWeather holds. Drawn every morning from the city's climate and season, the same sky the map shows.

Game:passTime(minHours, maxHours?)#

Advances the clock by a random number of hours in the range (one argument: exactly that much).

Game:setWeather(id, hours?) → bool#

Forces a weather type for hours game hours (nil or 0: until midnight), then the day's own weather comes back. setWeather(nil) lifts a forced weather. False (and a log line listing the known ids) for an unknown id. Fires the weatherChanged event.

Game:timeoutActor(hours, sceneId, actor, ...)#

For hours (scaled by the scene frequency), the scene's WHO no longer finds these people. Up to four actors.

Game:timeoutActorPrecise(hours, sceneId, actor, ...)#

timeoutActor for exactly hours.

Places

Game:enterVenue(tag [, preset])#

On the city map, walks the player into the first populated building of that venue tag (after forcing preset, when given). The room loads over the next frames: hold until Game:inRoom(tag). Returns false when the map is not up or the city has no such venue; in the room harness the stage already is the venue.

if Game:enterVenue("bar") then
  while not Game:inRoom("bar") do Game:Hold(0.5) end
end
Game:findNearbyBuilding(tag1, tag2?, tag3?) → text#

One of those venue types near the player.

Game:GetCurrentLocation() → text#

The venue tag of the player's current place.

Game:inRoom([tag])#

True when the player stands in a furnished room, of that venue tag when one is given. What a scene waits on after enterVenue.

while not Game:inRoom("home") do Game:Hold(0.5) end
Game:isAtHome() → boolean#

True at the player's home.

Game:moveTo(venueTag)#

Same as setBackground.

Game:OverwriteCurrentLocation(venueTag)#

Turns the current place into a place of that type (the room for that tag).

Game:roomLayout(tag, preset)#

Every room of that venue tag is furnished with the named shared preset (a mod's Rooms/Layouts/*.ulroomlayout, by its display name) for the rest of the session; "" clears it. For scenes that must play in the same room every time (a trailer, a tutorial).

Game:roomLayout("bar", "ul_trailer_bar")
Game:setBackground(venueTag)#

Moves the scene and the player to a place of that venue type.

Game:setBackground("park")

Also callable as setBakground, setBackgroundCustom.

Quests

Game:getActiveQuests() → { questId }#

The ids of every active quest, oldest first.

Game:getQuestStep(questId) → string#

The quest's current step line, or nil.

Game:isQuestActive(questId) → boolean#

True while that quest is running.

Game:isQuestCompleted(questId) → boolean#

True once that quest was completed.

Game:isQuestFailed(questId) → boolean#

True when the quest's last ending was a failure (completing it later clears this).

Game:openQuestJournal()#

Opens the quest journal.

Game:questEnd(questId?)#

Completes a quest and clears its objectives. Without an id: the active quest whose folder holds the running scene, else the last one started.

Game:questEnd("mymod_family")
Game:questFail([questId] [, reason]) → bool#

Ends a quest as failed: its objectives go as with questEnd, but it is not completed, so a ONCE quest can be started again. With no id, the quest whose folder holds the scene. Fires questFailed(id, reason).

Game:questFail('ynl_heist', 'caught')
Game:setQuestStep(questId, text)#

The line the journal and the map show under the quest: where the story stands. nil clears it.

Game:setQuestStep("mymod_family", "Collect from the bakery by Friday")
Game:startQuest(questId, definition?) → boolean#

Starts a quest; several can run at once. Its START scene runs after the current scene. With a table, defines a quest that has no .ulquest file (your mod's storyline): name, description, step, once (default true). False when it is already active or a completed once-only quest.

Game:startQuest("mymod_family", { name = "The Family Business", step = "Meet Sal at the docks" })

Jobs and money

Game:endPrison()#

Releases the player and clears the sentence.

Game:getPlayerMajor()#

The player's university major, or "".

Game:getSalary() → number#

The player's salary.

Game:imprison()#

Sends the player to prison. Set the sentence in the sentence stat first.

Game:isStudent() → boolean#

True when the player studies at a university.

Game:loseJob()#

The player loses their job: salary and workplace cleared, boss and colleagues back to acquaintances.

Game:moveFraternity()#

The building the player is in becomes their fraternity.

Game:moveJobs()#

The player is hired at the building they are in. Set salary and boss separately.

Game:moveSchools()#

The player enrols at the building they are in.

Game:quitCrime()#

The player leaves organised crime.

Game:quitFraternity()#

The player leaves their fraternity.

Game:quitLecturing()#

The player stops lecturing.

Game:quitMedical()#

The player leaves the medical career.

Game:quitSchool()#

The player leaves school.

Also callable as graduate.

Game:setFraternityFees(amount)#

Sets the player's fraternity fees.

Game:setSalary(amount)#

Sets the player's salary.

Game:setTuition(amount)#

Sets the player's tuition fees.

Game:startMayor()#

The player becomes mayor, at the building they are in.

Housing

Game:DatingHasHome() → boolean#

True when the player's partner has a home.

Game:endStay() → boolean#

Ends the temporary residence started by Game:stayAt and gives the previous home back. False when there was none.

Game:getRent() → number#

The player's rent.

Game:getStay() → {buildingId, daysLeft} | nil#

The current temporary residence: its building id and the days left (-1 when it lasts until Game:endStay), or nil.

Game:isAtDatingHome() → boolean#

True at the partner's home rather than the player's.

Game:loseHome()#

The player loses their home (moves in with their partner if the partner has one).

Game:loseHomeDating()#

The partner moves out of their home and in with the player.

Game:moveHome(buildingId?)#

With no argument, the building the player is in becomes their home. With a building id (Places:here().id, Places:buildings()) that building does, from anywhere. Returns false, and changes nothing, when no building of the current city has that id.

Game:PlayerHasHome() → boolean#

True when the player has a home.

Game:setRent(amount)#

Sets the player's rent.

Game:stayAt(buildingId?, days?) → boolean#

A temporary residence: the building (the one the player is in when no id) is the player's home for days days (nil or 0: until Game:endStay). The "home" venue tag and isAtHome follow it, and the home the player left reads as somebody else's. When it ends, the old home comes back. A refuge, a hotel, a friend's sofa.

Business

Game:AddEmployee(venueTag, person, salary) → boolean#

Hires a person at the business.

Game:calculateExpenses() → number#

Its expenses.

Game:calculateRent() → number#

The rent of the business the player is in.

Game:calculateRevenue() → number#

Its revenue.

Game:calculateWages() → number#

Its total wages.

Game:IsBusiness(venueTag) → boolean#

True when there is a business there.

Game:ModifyReputation(amount)#

Changes its reputation.

Game:OpenBusinessManagement(venueTag)#

Opens the business management overlay.

Game:OpenShop(shopId)#

Opens the shop overlay for a .ulshop (its file name).

Game:OpenShop("ynl_bar_merch")
Game:StartBusiness(venueTag, name, owner, salary) → boolean#

Starts a business at that venue type, owned by owner.

Game:startBusiness() → boolean#

The venue the player stands in becomes their business (this building, not every venue of its type), under the name the player typed in the naming prompt, else "<first name>'s <venue>". The staff working in the room stay on as employees; with nobody at work, a manager is hired. false outside a venue.

if Game:startBusiness() then Game:Narrate("The keys are mine.") end
Game:stopBusiness()#

Closes the player's business in the venue they stand in. StopBusiness(venueTag) closes one by key.

Game:StopBusiness(venueTag)#

Closes the business.

Sex scenes

Game:advanceSexProgress(seconds)#

Low level: advances the participants towards climax.

Game:checkSexCucking(cuckold, impregnator, mother)#

Low level: cuckolding consequences.

Game:checkSexRape() → boolean#

Low level: evaluates consent for the running session and flags forced participants.

Game:checkSexSTD(person, partner) → boolean#

Low level: rolls an STD between two participants.

Game:checkSexVirgin(person, partner, tags) → boolean#

Low level: records a lost virginity if the tags say so.

Game:clearSexBondage(person)#

Low level: removes a participant's bondage.

Game:continueSexPOV() → boolean#

Low level: point-of-view camera.

Game:endSexScene()#

Low level: ends the running session.

Game:Filter(tag1, tag2?, tag3?)#

Limits the next sex scene to animations with these tags.

Game:Filter("Oral")
Game:isSexSceneActive() → boolean#

Whether a sex scene is running.

Game:isUsingCondom() → boolean#

Whether a condom is used.

Game:moveSexSceneHome() → boolean#

Low level: moves the session to the player's home.

Game:playSexAnimation(animId) → boolean#

Low level: plays that animation in the running session.

Game:resetSexCamera()#

Low level: default camera.

Game:selectSexAnimation({ tags }) → text#

Low level: picks an animation id matching the tags, or nil.

Game:setSexSpeed(speed)#

Low level: animation speed of the running session.

Game:setUsingCondom(on)#

Condom for this scene: no pregnancy.

Game:Sex(a, b, …)#

Starts an interactive sex scene with up to six people (order sets the roles) and waits until the player finishes. Applies the consequences afterwards (affairs, virginity, pregnancy, STDs).

Game:Sex(Player, Actor)
Game:SexNoAffair(a, b, …)#

Like Sex, without the affair check.

Game:startSexScene({ people }) → boolean#

Low level: starts a session without waiting. Prefer Sex().

Game:switchSexCamera(index) → boolean#

Low level: switches the session camera.

Game:TalkNonConsensual([forcer])#

Uses the non-consensual dirty-talk lines in the next sex scene. Name the person forcing it: the next Sex() is then recorded as a sexual assault by them on the others (Witness). Without an argument nothing is recorded.

Game:talkSexDirty(person) → text#

Low level: a dirty-talk line for that participant, from the .ultalk banks.

Game:toggleSexGravity(person, on)#

Low level: physics on or off for a participant.

Game:updateSexBondagePose(person)#

Low level: re-applies a participant's bondage pose.

Pregnancy and health

Game:blockPregnancy()#

No pregnancy from any sex in this scene.

Game:contractSTD()#

The player catches an STD.

Game:countPregnancyDays() → number#

Days of the player's pregnancy.

Game:hasSTD() → boolean#

True when the player has an STD.

Menus

Game:openMenu(name)#

Opens a game menu: CharGen, Inventory, ModManager (the others are not built yet).

Game:openWardrobe()#

Opens the player's own wardrobe without waiting for it (the scene goes on).

Game:showWardrobe(person, mode) → value#

Opens the wardrobe on person and waits. "give": the player picks one of their garments that fits; returns its id, or nil if cancelled. Nothing changes hands until you call giveClothing. "suggest": the player dresses them for an occasion from both wardrobes (a preview, put back on closing); returns { occasion = "work", items = { ids } } or nil. Your scene decides whether they accept. "self": the player's own wardrobe; returns nil when they are done. "shop" (or "shop:<id>"): the venue's clothes shop in the fitting room; the player tries pieces on and buys the basket; returns the ids bought ({} when nothing).

local pick = Game:showWardrobe(Actor, "suggest")
if pick and Actor:GetStat("rapportwithplayer") > 20 then
	Actor:setOutfit(pick.occasion, pick.items, true)
	Actor:wearOutfit(pick.occasion)
end

Utilities

Game:isModEnabled(modFolder) → boolean#

True when that mod is installed and enabled. Guard calls into other mods with it.

if Game:isModEnabled("ul_Health") then
Game:Log(text)#

Writes a line to Saved/Logs/Underlives.log.

Game:Log("ynl: stage=" .. tostring(stage))
Game:PickRandom({ values }) → value#

One random element of a list; nil for an empty list.

Game:PreciseModify()#

Stat changes in the rest of this scene are not scaled by difficulty.

Game:Random(min, max) → number#

A random number between min and max. With two whole-number bounds it is a whole number, both ends included, so list[Game:Random(1, #list)] works; otherwise a decimal.

if Game:Random(0, 100) < 30 then
Game:Seed(value)#

Fixes the random draws that follow (Random, PickRandom, who the extras are), so a beat replays the same.

Game:Seed(7)

Legacy

Game:clearGetList()#

Legacy. Does nothing: lookups never exclude people returned earlier.

Game:removeAddedClothes()#

Legacy: took back clothes a modelling scene lent. Does nothing (there is no loaned wardrobe).

Game:setBackground3D(file)#

Legacy: loaded a hand-built 3D room. Rooms are generated now; call setBackground instead. Does nothing.

Game:SneakGame()#

Legacy mini-game. Does nothing (mini-games are not part of this game); the scene's own sneak roll decides.

Game:TfGame() → boolean#

Legacy "transformation start" check. Always false.

Perks

Game:buyPerk(id) → ok, reason#

Buys a perk with the player's perk points (the perks stat), as the HUD's Perks page does: a perk of tier N needs one of tier N-1 in its branch, and its requires. Its stats become the modifier perk:<id> and perkUnlocked fires. On refusal, the reason.

local ok, why = Game:buyPerk("mymod_night_owl")
if not ok then Game:Narrate(why) end
Game:getPerkPoints() → number#

The player's unspent perk points. Give points with Player:ModifyStat("perks", n).

if Game:getPerkPoints() >= 3 then ... end
Game:getPerks() → table#

The whole perk tree (Perks/*.ulperk of every mod): a list of { id, name, text, branch, tier, cost, owned, why, mod }. why is nil when the player can buy it now, else the reason ("Needs 2 perk points.").

for _, perk in ipairs(Game:getPerks()) do if perk.owned then ... end end
Game:grantPerk(id) → bool#

Gives a perk for free, ignoring cost and tier (a quest reward). False when unknown or already owned.

Game:grantPerk("mymod_night_owl")
Game:hasPerk(id) → bool#

Whether the player owns that perk. This is how a perk does more than stat bonuses: your scenes and ticks ask it.

if Game:hasPerk("ul_soc_listener") then ... end
Game:resetPerks(refund?) → number#

Takes every perk back and, unless refund is false, returns the points paid for them (granted perks cost nothing). Returns the points refunded; fires perksReset.

local back = Game:resetPerks()

Trips away

Game:comeBack() → bool#

Ends the trip now (the player can also, from the banner). False when not away.

Game:comeBack()
Game:getAway() → table#

The trip in progress: { place, mod, left, returns, hoursLeft, climate } (hours since the game began), nil at home.

local trip = Game:getAway()
Game:goAway({ place, days | hours, mod, climate, hemisphere }) → bool#

The player leaves the city for a while (a holiday, a cruise, a ski week). Until the return time the location is "away": only actions and scenes whose WHERE names "away" are on offer ("all" means anywhere in the city), the city's buildings cannot be entered, a banner shows where and until when, and the weather is climate's (a climate of Weather/*.ulweather; hemisphere = "south" swaps its seasons). At the return time the player is home and awayChanged fires. False when already away or without a place or duration.

Game:goAway({ place = "Barcelona", days = 7, climate = "mediterranean", mod = M })
Game:isAway() → bool#

Whether the player is on a trip away from the city.

if Game:isAway() then return false end

Snapshots

Game:deleteSnapshot(name) → bool#

Removes a snapshot (the loop is broken).

Game:deleteSnapshot("mymod_loop_morning")
Game:hasSnapshot(name) → bool#

Whether a snapshot of that name exists for this life (a snapshot of another playthrough does not count).

if not Game:hasSnapshot("mymod_loop_morning") then Game:saveSnapshot("mymod_loop_morning") end
Game:restoreSnapshot(name, keep?) → bool#

Puts the game back as the snapshot left it: clock, money, stats, people, everything. It happens once the scene (or event handler) is over, never under it, then snapshotRestored fires. keep lists player stats or vars whose current value survives: what the loop remembers. False when there is no snapshot of that name in this life.

Game:restoreSnapshot("mymod_loop_morning", { "mymod_loop_count", "mymod_loop_clues" })
Game:saveSnapshot(name) → bool#

Saves the whole game in a slot of its own (for a time loop: the morning of the day that repeats). Prefix the name with your mod's.

Game:saveSnapshot("mymod_loop_morning")

Phone

Game:getPhoneMessages(from?) → table#

One conversation (a person or a sender's name), or every message: { { id, from, with, person, text, hours, read, call, mine, mod } }, oldest first. from is "You" for the player's own, with the other side.

for _, m in ipairs(Game:getPhoneMessages(friend)) do ... end
Game:getPhoneUnread() → number#

How many messages the player has not read.

if Game:getPhoneUnread() > 5 then ... end
Game:markPhoneRead(from?) → number#

Marks a conversation (or everything) read; returns how many messages were unread. Opening a conversation on the phone page does the same.

Game:markPhoneRead("Mum")
Game:SendPhoneMessage(from, text, { mod, call, fromPlayer, silent, name }?) → id#

A text (or with call = true, a missed call) on the player's phone, saved in from's conversation: a person (actor or reference) or a sender's name ("Mum", "Barclays"). It rings the bell (folded per conversation, opening it) unless silent; fromPlayer = true records the player's own reply. Never starts a scene. Returns the message id, nil without text or sender. Both spellings work: SendPhoneMessage and sendPhoneMessage.

Game:SendPhoneMessage(friend, "Coffee tomorrow?", { mod = M })

Location

Game:getRoomFurniture(match?) → { {name, kind, key}, ... }#

The furniture of the room the player is in, optionally only pieces whose kind contains `match` ("Sofa", "TV", "Bed", "Seating_"). `kind` is the pack's label, e.g. "Seating_Sofa+2Seat"; `name` is its short form ("Sofa").

Game:refurnishRoom() → boolean#

Forgets the saved layout of the room the player is in: it is furnished afresh on the next visit (new furniture bought).

Game:removeRoomFurniture(match, max?) → { name, ... }#

Takes matching pieces out of the room the player is in (bailiffs, a burglary): `max` pieces, default 1, 0 for all. The room's layout is saved, so they stay gone on later visits. Returns the names taken; an empty match takes nothing. Add an item to the inventory yourself if the piece should be recoverable.

Player

Game:switchPlayerTo(Actor, { formerJob }) → string#

Play continues as that person (someone the player knows: a grown-up child, an heir). They keep their own look, name, stats, job and family; Player now refers to them. The former player becomes a person the new one knows, with formerJob as their job if given ("Deceased"). Returns the former player's id (for Game:getPersonById), nil when it cannot be done. Fires playerSwitched(oldId, newId). Hand over money or items before switching.

local former = Game:switchPlayerTo(Child, { formerJob = "Deceased" })