// Radio command (design §6, the Head of Security finale): NPC staff work the // roles you aren't, and the radio is how you reach them. You used to speak // into the radio; now you're the voice on the other end. Competence varies — // that IS the staff. Pure numbers here; the scenes own the walkie theatre. /** Orders the floor staff take. 'mess' is Bump the glassie, 'water' is Shan. */ export type FloorOrderKind = 'mess' | 'water'; export type OrderAck = 'sent' | 'cooldown' | 'nothing'; export const RADIO_COOLDOWN_MS: Readonly> = { mess: 45_000, water: 60_000, }; /** Staff cross a real floor — an order lands, then happens. */ export const ORDER_LAG_MS: readonly [number, number] = [3000, 7000]; /** Bump mops AND signs (in that order, worryingly) this often; else he signs * it and finds a phone in the puddle. */ export const BUMP_MOP_CHANCE = 0.65; /** Shan gets the water in without a negotiation this often; else she leads * with the phrase "you've had enough". */ export const SHAN_CLEAN_CHANCE = 0.8; /** A firm two cups. */ export const SHAN_WATER_STEP = 0.14; export const SHAN_BOTCH_AGGRO = 2; export const ORDER_DONE_VIBE = 1; /** Shan only bothers with loose and worse. */ export const SHAN_MIN_INTOX = 0.45; /** Kayden holds the rope this long, then resumes ruling. Badly. */ export const KAYDEN_HOLD_MS = 60_000; export const KAYDEN_HOLD_COOLDOWN_MS = 90_000; export function rollBumpMops(rng: { chance(p: number): boolean }): boolean { return rng.chance(BUMP_MOP_CHANCE); } export function rollShanClean(rng: { chance(p: number): boolean }): boolean { return rng.chance(SHAN_CLEAN_CHANCE); } export function orderLag(rng: { int(min: number, max: number): number }): number { return rng.int(ORDER_LAG_MS[0], ORDER_LAG_MS[1]); }