SigmaBoyRPG
The whole of **Sigma Boy RPG** in one component: run state, the school, the turn-based battle engine, every zui screen, the audio mix, and persistence.
SigmaBoyRPG
The whole of Sigma Boy RPG in one component: run state, the school, the turn-based battle engine, every zui screen, the audio mix, and persistence.
Attach it to one manager entity in the scene. Each client runs its own instance, so a run is local to the player while the world stays shared.
What it builds
awake() spawns the five zones — Hallway, Cafeteria, Gym, Detention,
Principal's Office — laid out along +X, each with its own floor, walls,
props, coloured light, foes, and NPCs. Every spawned entity is
temporary, so it never enters a scene save; the component is the sole
owner and onDestroy clears it.
Fields
| Field | Meaning |
|---|---|
skipTitle | Open straight into the overworld instead of the title screen. |
mode | Live game mode (title, overworld, battle, …). Read-only in practice. |
zone | Zone the player is roaming. |
aura | Live aura — HP, currency, and social power in one number. |
level | Live level. |
Methods
startRun(period)— begin a fresh run at a period (1–5).forceBattle(foeId, count)— drop straight into a battle againstcountcopies of a roster id.press(id)— fire a UI callback by id; the same path a click takes.snapshot()— a table of live state for assertions.
Controls
sigma_controls.inputMap binds them: WASD to roam, E to
interact, Escape to pause, 1–4 for the battle commands, and
Backspace to back out of a battle submenu.
Persistence
Levels, gear, bestiary entries, bosses beaten, best-run aura, and the
settings live in runtime_data.player(localId()) under sigma/. A
checkpoint is written at every bell, so CONTINUE and
RETRY FROM LAST BELL resume from the last period boundary.
Dependencies
sigma_data— zones, roster, skills, items, gear, dialogue.sigma_ui— every widget tree.sigma_audio— bakes thesig_*soundClips this component plays.SigmaCam— the top-down camera it retargets for battles.
Interface
What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.
conforms to
zero/source-extract/v2SigmaBoyRPG — the whole game. One component owns the run state, the school, the turn-based battle engine, every zui screen, the audio mix, and persistence. It lives on a single manager entity in the scene; each client runs its own instance, so the run is local to the player while the world stays shared. Layout of this file: 1. constants + clip table 6. battle engine 2. state 7. dialogue + shop 3. persistence 8. UI assembly 4. audio 9. callbacks 5. world building 10. lifecycle
setOverhead(f: FoeInstance, telegraph: string?) → void
Rewrite a foe's overhead label. Passing nil restores the bare name.
| arg | type | description |
|---|---|---|
| f | FoeInstance | |
| telegraph | string? |
store( ) → void
saveProfile( ) → void
saveCheckpoint( ) → void
loadPersisted( ) → void
hasCheckpoint( ) → boolean
ensureAudioRig( ) → void
ensureListener( ) → void
setBed(entId: string?, current: string, key: string, gain: number) → string
Swap a looping bed. A clip only starts on `play()`; setting `clip` and `volume` alone leaves the source silent.
| arg | type | description |
|---|---|---|
| entId | string? | |
| current | string | |
| key | string | |
| gain | number |
setMusic(key: string) → void
| arg | type | description |
|---|---|---|
| key | string |
setAmbient(key: string) → void
| arg | type | description |
|---|---|---|
| key | string |
sfx(key: string, vol: number?) → void
| arg | type | description |
|---|---|---|
| key | string | |
| vol | number? |
applyMix( ) → void
setBackdrop(rgb: { number }) → void
Each zone gets its own background wash, visible above the walls at the camera's tilt. `sky.set` is the plain global for this — the `lighting` toolbox does the same job but a tool reference cannot be statically pinned, so the publish gate refuses content that calls it. The backdrop above the walls is a graded sky rather than one flat colour: the zone's mood tint darkens toward the zenith and lifts toward the horizon, so the top of the frame has depth instead of a hard band. Only the colours are set — leaving `type` alone keeps the procedural sky the scene was built with, which is also what lights the metal.
| arg | type | description |
|---|---|---|
| rgb | { number } |
surfaceMaterial(role: string, tint: { number }) → any
| arg | type | description |
|---|---|---|
| role | string | |
| tint | { number } |
emissiveMaterial(tint: { number }, strength: number) → any
Self-lit surfaces for the light fixtures. These are what the bloom pass catches, so the emissive value runs well above 1.0 — the fixture reads as a source rather than a pale patch of wall.
| arg | type | description |
|---|---|---|
| tint | { number } | |
| strength | number |
tintModel(e: any, mesh: string, tint: { number }, role: string?) → void
| arg | type | description |
|---|---|---|
| e | any | |
| mesh | string | |
| tint | { number } | |
| role | string? |
block(name: string, x: number, y: number, z: number, sx: number, sy: number, sz: number, tint: { number }, collide: boolean, role: string?) → void
| arg | type | description |
|---|---|---|
| name | string | |
| x | number | |
| y | number | |
| z | number | |
| sx | number | |
| sy | number | |
| sz | number | |
| tint | { number } | |
| collide | boolean | |
| role | string? |
nameLabel(anchor: any, text: string, color: string, height: number, size: number) → string
Labels are their own top-level entities rather than children: a child inherits the foe's non-uniform scale, and `billboard` rolls the text under a pitched camera. The overworld camera holds a fixed yaw of 0, so an unbillboarded label facing +Z reads square to the screen.
| arg | type | description |
|---|---|---|
| anchor | any | |
| text | string | |
| color | string | |
| height | number | |
| size | number |
buildZone(z: any) → void
| arg | type | description |
|---|---|---|
| z | any |
clearWorld( ) → void
Sweep by NAME PREFIX, not just this instance's OWNED list. A component reload (hot-reload, remove/re-add, an edit->play flip) hands the new instance an empty list while the previous instance's entities are still in the world; tracking only OWNED would leak a whole duplicate school every reload, complete with duplicate colliders.
buildSchool( ) → void
localAvatar( ) → any
controller( ) → any
freezePlayer(on: boolean) → void
| arg | type | description |
|---|---|---|
| on | boolean |
sigmaCam( ) → any
placePlayerAt(zoneId: string) → void
| arg | type | description |
|---|---|---|
| zoneId | string |
toast(text: string, tone: string) → void
| arg | type | description |
|---|---|---|
| text | string | |
| tone | string |
banner(text: string, tone: string, life: number?) → void
| arg | type | description |
|---|---|---|
| text | string | |
| tone | string | |
| life | number? |
stats( ) → void
maxAura( ) → number
addAura(delta: number, silent: boolean?) → void
| arg | type | description |
|---|---|---|
| delta | number | |
| silent | boolean? |
grantLevels( ) → void
logLine(text: string) → void
| arg | type | description |
|---|---|---|
| text | string |
foeCardX(idx: number) → number
| arg | type | description |
|---|---|---|
| idx | number |
floatText(text: string, tone: string, x: number, y: number, size: number?) → void
| arg | type | description |
|---|---|---|
| text | string | |
| tone | string | |
| x | number | |
| y | number | |
| size | number? |
playerAtk( ) → number
rollDamage(atk: number, mult: number, def: number) → void
| arg | type | description |
|---|---|---|
| atk | number | |
| mult | number | |
| def | number |
livingFoes( ) → number
firstLivingIndex( ) → number
damageFoe(idx: number, dmg: number, crit: boolean, source: string) → void
| arg | type | description |
|---|---|---|
| idx | number | |
| dmg | number | |
| crit | boolean | |
| source | string |
damagePlayer(dmg: number, label: string) → void
| arg | type | description |
|---|---|---|
| dmg | number | |
| label | string |
setQueue(f: FoeInstance) → void
Decide the foe's NEXT move and publish it overhead. The move id chosen here is the one `foeAct` executes, so the telegraph is a promise, not a hint: a player who reads it can counter it.
| arg | type | description |
|---|---|---|
| f | FoeInstance |
buildOrder( ) → void
endBattle(victory: boolean) → void
| arg | type | description |
|---|---|---|
| victory | boolean |
beginTurn( ) → void
advanceTurn( ) → void
foeAct(f: FoeInstance, idx: number) → void
Execute the move the foe telegraphed last turn, then telegraph the next one. Every branch here is reachable only if `setQueue` published the matching id, so the overhead text and the action always agree.
| arg | type | description |
|---|---|---|
| f | FoeInstance | |
| idx | number |
startBattle(foeKeys: { string }, fromDialogue: boolean) → void
| arg | type | description |
|---|---|---|
| foeKeys | { string } | |
| fromDialogue | boolean |
checkBattleEnd( ) → boolean
playerAttack( ) → void
playerSkill(id: string) → void
| arg | type | description |
|---|---|---|
| id | string |
playerItem(id: string) → void
| arg | type | description |
|---|---|---|
| id | string |
playerMog( ) → void
openDialogue(dialogueId: string) → void
| arg | type | description |
|---|---|---|
| dialogueId | string |
answerDialogue(index: number) → void
| arg | type | description |
|---|---|---|
| index | number |
closeDialogue( ) → void
openShop( ) → void
buyItem(id: string) → void
| arg | type | description |
|---|---|---|
| id | string |
zoneFoesLeft(zoneId: string) → number
| arg | type | description |
|---|---|---|
| zoneId | string |
applyZone(zoneId: string) → void
| arg | type | description |
|---|---|---|
| zoneId | string |
ringBell(reason: string) → void
| arg | type | description |
|---|---|---|
| reason | string |
abortBattle( ) → void
Drop any battle in progress without paying out. Every entry point that changes what run you are in has to call this, or the previous fight's actors keep taking turns underneath the new one.
bestOwnedGear( ) → void
Gear is profile progression, not run progression: a new run starts wearing the best piece already owned in each slot.
newRun(period: number) → void
| arg | type | description |
|---|---|---|
| period | number |
continueRun( ) → boolean
toTitle( ) → void
skin( ) → void
bestiaryCount( ) → number
bossCount( ) → number
hudTree( ) → any
battleMenuItems( ) → void
battleTree( ) → any
statusTree( ) → any
extrasTree( ) → any
endingLines( ) → void
overlayTree( ) → any
refreshUi( ) → void
enterSettings(fromPause: boolean) → void
| arg | type | description |
|---|---|---|
| fromPause | boolean |
onCallback(id: string, data: any) → void
| arg | type | description |
|---|---|---|
| id | string | |
| data | any |
nearestInteractable(av: any) → void
| arg | type | description |
|---|---|---|
| av | any |
touchedFoe(av: any) → void
| arg | type | description |
|---|---|---|
| av | any |
tickBattle(dt: number) → void
| arg | type | description |
|---|---|---|
| dt | number |
tick(dt: number) → void
| arg | type | description |
|---|---|---|
| dt | number |
startRun(period: number) → void
Start a fresh run at a period. Exposed so tests and tooling can drive the game without clicking through the menus.
| arg | type | description |
|---|---|---|
| period | number |
forceBattle(foeId: string, count: number) → void
Force a battle against a roster id, bypassing the overworld.
| arg | type | description |
|---|---|---|
| foeId | string | |
| count | number |
press(id: string) → void
Fire a UI callback by id — the same path a click takes.
| arg | type | description |
|---|---|---|
| id | string |
snapshot( ) → void
Snapshot of live game state for assertions.
awake( ) → void
start( ) → void
update(dt: number) → void
| arg | type | description |
|---|---|---|
| dt | number |
editorUpdate(_dt: number) → void
| arg | type | description |
|---|---|---|
| _dt | number |
onDestroy( ) → void
Sub-parts
Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.
Problems
Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.
Inside
3 problems across 1 itemagent_score is exposed.+ quality × 0.35
+ performance × 0.25
± compat factor
Usability ratings
Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".
Scoped to this part · feeds back into the world's score.