Core
The one table every part of GREASEPAINT reads. It carries the game's constants — the cards, the four clowns, the barker's lines, the palette and the fonts — the live state of the night, and the event bus the game talks over. Every other module requires this and nothing else of ea…
Core
The one table every part of GREASEPAINT reads. It carries the game's constants — the cards, the four clowns, the barker's lines, the palette and the fonts — the live state of the night, and the event bus the game talks over. Every other module requires this and nothing else of each other.
game.rules.Director is the only writer of Core.state(). Everything
else reads the state, listens on the bus, and asks the Director for changes
through Core.cmd.
local Core = require("game.Core")
Core.state().nerve -- read the night
Core.on("clown.hit", function(p) ... end) -- react to it
Core.cmd("playCard", { index = 2 }) -- ask the Director to act
Constants
Core.RULES— Nerve, Breath, hand size, the Laughter ceiling and where the meter carries to after a laugh, how warm the house can get and what a step of heat is worth, what a held Grin bites, how many acts a night runs, which act's interval takes a card away instead of giving one, the starter deck and the reward pool.Core.CARDS— the twelve cards, each withkind(gag/guard/trick/curse),cost, and whatever it does:dmg,block,heal,laughter,effect(weaken/reflect/burn),exhaustwhen playing it takes it out of the act, and thetextits face prints.Core.CLOWNS— Pinch, Bello, Slats and Mr. Marrow:hp, a loopingpatternof intents, and three spokenlines(enter,laugh,die).Core.RUN— the three-clown pool and the finale.Core.BARKER— the Ringmaster's four narrated lines, andheat, the one he marks each step of the warming house with.Core.PALETTE/Core.FONTS/Core.ANCHORS/Core.SEAT/Core.PHASES/Core.EVENTS/Core.COMMANDS.
State
Core.state()— the live night. Phase, act, turn, Nerve, Breath, Block, Laughter, theheatthe house has reached, thelibrary(every card the night owns) and the working piles drawn from it (deck,hand,discard,exhaust), the currentclown, therewardon offer — itscards, thenextclown it names and itsmode(takeorleave) — the focused index, and theorderthe four acts run in.Core.reset()— replaces the state with a fresh night, in place, so a reference held across a restart stays valid.
The bus
Core.on(name, fn, tag?) -> unsubscribe— subscribe. Atagmakes it idempotent: registering the same event and tag again replaces the earlier subscription rather than stacking a second copy, which is what keeps a reloaded component from handling everything twice.Core.off(name, tag)— drop a tagged subscription.Core.emit(name, payload)— fire to every subscriber, in order. A listener that errors is reported and the rest still run.Core.cmd(name, payload)—Core.emit("cmd." .. name, payload).Core.listenerCount(name),Core.clearListeners().
Chance
The night's randomness is one stream, seeded per run, so a seed replays a whole night: the act order, the shuffles, which card the tent paints, which three cards a reward offers.
Core.random()— the next value in [0, 1).Core.randomIndex(n)— an integer in [1, n].Core.shuffle(list)— shuffle in place, return the list.Core.rand(salt)— a stable value for a salt, independent of the stream.
The frame
Every screen, plate and card lays out from the live frame, so any shape holds.
Core.frame(override?)—{ w, h, u, wide }.uis a hundredth of the short side: the unit every proportion is stated in.wideis true from an aspect of 1.25 up. Pass{ width, height }to lay out against a shape the engine is not running at.Core.rgba(hex, a)— a palette hex with an alpha, as thergba()string a widget takes.Core.hairline(n)— a rule ofnpixels, never thinner than one whole one.
Also
Core.card(id)/Core.clown(id)— a record, or nil.Core.readingTime(text)— how long a spoken line should sit on screen, in milliseconds, when no generated clip has answered for it. Between 1.4 and 9 seconds, whatever the length.
Scoped to this part · feeds back into the world's score.