Lua scripting

Places

Know which building the player is in, keep your mod's state for that building, register businesses the player owns on the map, and send the player away on a trip.

A venue type ("cafe") is every cafe in the city. When your story, your regulars or your opening happen at one cafe, keep them on that building with Places.

lualocal M = "ynl_Nightlife"

local here = Places:here()                 -- { id, name, tag, city }, nil outdoors
if here then
	local visits = (Places:get(M, "visits") or 0) + 1
	Places:set(M, "visits", visits)        -- this building only
	Places:set(M, "host", host:id())       -- a person id: the same host on the next visit
end
  • A building's id is stable: "London:-70785:10249", the city and the building's position. It survives saves, reloads and the city being rebuilt, and is the same id the agenda, jobs (Work:snapshot().building) and notifications use.
  • Places:get(mod, key [, building]) and Places:set(mod, key, value [, building]) default to the building the player is in. Values are numbers or strings; nil removes one. Without a building (outdoors), set returns false.
  • Places:buildings(mod) lists where your mod has kept something, with the building's name and city, so you can tell the player "it continues at Café Lune" from anywhere.
  • Places:city(id) gives the city part: a story begun in another city can say so rather than continue in a stranger's venue.
  • Values stay saved while your mod is turned off.

A place's state is not a room change: furniture and people placed in the room are separate (room presets).

Call Does
Places:here() { id, name, tag, city }, or nil outdoors.
Places:home() { id, city } of the player's home building, or nil when they have none.
Places:get(mod, key [, building]) A value, nil when unset.
Places:set(mod, key, value [, building]) true, or false without a building.
Places:buildings(mod) { { id, name, city } }
Places:city(building) The city of a building id.
Places:version() The API version, 1.

Objects in the room

The small things standing in the room the player is in (a mug, a radio, papers on a desk) can be listed, taken and put down. They are the objects the player clicks (see Things in rooms); what changes is saved per building and room.

luafor _, prop in ipairs(Room:props("Radio")) do
	if prop.owner ~= "player" then
		local item = Player:take(prop)              -- into the inventory (item id); raises propTaken
		break
	end
end

Actor:putDown("radio_portable", "Desk")             -- on the nearest desk in reach, else any surface, else the floor
Call Does
Room:props([word]) { { key, item, name, piece, owner, shop, handheld, x, y, z } }: every object of the venue the player is in, or only those whose piece name contains word. Empty outdoors.
Actor:take(prop) A prop (an entry of Room:props() or its key) goes into this person's inventory wherever they stand. Returns the item id, nil when there is no such prop. Raises propTaken when it was not theirs.
Actor:putDown(item [, where]) An item of their inventory that has a room piece is put down near them: on the nearest surface whose piece name contains where, else on any surface in reach, else on the floor. Returns the new prop's key, nil when it could not.
Actor:putDown() Without an item: what they carry in a hand goes back where it was taken from (Actor:pickUp).
Room:stock([shop]) { { shop, item, name, price, left, sold, shown } }: what the shops of the venue the player is in sell in this building (left = -1: unlimited; sold since the last restock; shown = how many stand on the shelves). Optionally one .ulshop id. Empty outside a shop.
Room:buy(item [, count [, shop]]) The player buys from the venue's shop that sells item (or from shop), paying as at the till: the stock goes down and as many props leave the shelves. true when bought. Raises itemBought.

item is the item id the object gives: the .ulitem whose Piece: names it, else piece:<Set>/<Node>; on a shop's shelf, the item the shop sells it as. owner is player, home:<building id>, venue, shop:<shop id> (stock; shop then holds the shop id), person:<id> (put down by someone) or public.

Home storage

What the player keeps at home: the food in the fridge and the pantry, the toiletries in the bathroom cabinet (see Home storage). Works wherever the player is.

luaif not Home:has("stock_meal") then
	-- nothing fresh to eat at home: offer the shop, a takeaway or eating out instead
end

for _, line in ipairs(Home:storage("fridge")) do
	if line.spoiled then Home:bin(line.item) end
end

Home:take("grocery_juice")                          -- one carton into the player's inventory
Call Does
Home:storage([kind]) { { item, name, count, units, day, freshness, spoiled, kind, container } }: what is stored in the player's home, in containers of kind (fridge, pantry, bathroom, wardrobe, drawer, counter...) or all. count is packs, units portions, day the purchase day, freshness 1 (new) to 0 (at its date). Garments are cloth:<id>.
Home:has(what) true when fresh portions at home match what: an item id, a stock stat (stock_meal), a storage kind (fridge) or an item category (Consumable).
Home:take(item [, count]) Packs of item (oldest first) out of home storage into the player's inventory. Returns how many came out.
Home:bin([item]) Throws away what is spoiled (of item, or all). Returns how many packs.
Home:kindOf(item) The storage kind an item is put away in: a container kind, carry or place.

Events: storageChanged (container key, item id, delta), spoiledEaten (item id, stock stat).

Businesses the player owns

A food truck, a franchise, a market stall or a web shop is more than a stat: register it with Businesses and the map knows about it. A player's business on a building is pinned wherever the camera is, as a filled green badge with your icon and its name, and any mod can ask what the player runs and where.

lualocal M = "ul_FoodTruck"

-- bought the truck while standing at the market
Businesses:register(M, { id = "truck", kind = "food_truck", name = "Taco Joe's", icon = "fast_food", building = "here" })

-- an online shop has no premises: no building, no pin
Businesses:register(M, { id = "web", kind = "web_shop", name = "Joe's Online" })

-- on the premises, from any mod
local b = Businesses:at()       -- the player's business here, or nil
if b and b.kind == "food_truck" then ... end

Businesses:unregister(M, "truck")   -- sold: the pin goes
  • building is "here", a building id (Places:here().id, Places:home().id), or nothing.
  • icon is a picture in Map/Icons/Locations/ (the venue icons), without .png.
  • owner = person registers someone else's business (a rival, a partner's shop); without it, it is the player's. Only the player's are pinned.
  • Takings and stock stay yours: pay through the Ledger so they show in the wallet, keep stock in Places or your globals.
  • Entries are saved, and stay while your mod is turned off.
Call Does
Businesses:register(mod, def) "mod/id", or nil for an unknown mod or no id. Registering an id again updates it.
Businesses:unregister(mod, id) true when there was one.
Businesses:get(mod, id) { mod, id, key, kind, name, icon, building, city, player, owner, opened }, or nil.
Businesses:list(mod?) Your mod's businesses, or everyone's.
Businesses:at(building?) The player's business there (default: here), from any mod.

Trips away from the city

A holiday, a cruise or a ski week does not need another city's map: the player is simply away for some days.

lualocal M = "ul_Holidays"

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

-- your actions for the trip: WHERE = { "away" }
-- on the way back:
Events:on(M, "awayChanged", function(what, place, mod)
	if what == "back" and mod == M then ... end
end)

While away:

  • The location is "away". Actions and scenes are offered there only when their WHERE names "away": "all" means anywhere in the city and does not follow the player on holiday.
  • The city's buildings cannot be entered. A banner under the clock says where and until when, with Skip to the end (the days pass) and Come back now.
  • The weather is the destination's (climate from Weather and seasons, hemisphere = "south" to swap the seasons); without climate, the home city's.
  • The clock runs as usual. At the return time the player is home (outside, on the map), a notification says so and awayChanged fires with "back".
  • A trip is saved: a game saved on the beach loads on the beach.
Call Does
`Game:goAway({ place, days hours, mod, climate, hemisphere })`
Game:comeBack() Ends the trip now.
Game:getAway() { place, mod, left, returns, hoursLeft, climate }, or nil at home.
Game:isAway() Whether the player is away.