{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://git.thewichersfamily.com/thethreemagi/sprite-catalog/raw/branch/main/schema/sprite-catalog.schema.json", "title": "Sprite catalog season file", "description": "One file per season. Variants are nested under their base sprite to avoid repeating base_name and row_name; the bot flattens them to one row per variant on load.", "type": "object", "additionalProperties": false, "required": ["season", "game_mode", "sprites"], "properties": { "season": { "type": "string", "pattern": "^c[0-9]+s[0-9]+$", "description": "Season identifier, e.g. c7s3. Must match the filename stem." }, "game_mode": { "$ref": "#/$defs/gameMode", "description": "Default game mode for every sprite in this file. Individual sprites may override it." }, "cross_mode_trading": { "type": "boolean", "default": false, "description": "Whether sprites from different game modes may be matched against each other. Defaults to false; leave it false unless the policy is deliberately changed." }, "notes": { "type": "string", "description": "Free text. JSON has no comments, so anything you would have written as one goes here." }, "sprites": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/sprite" } } }, "$defs": { "gameMode": { "type": "string", "enum": ["br", "og", "reload", "festival", "rocket_racing", "lego"], "description": "Extend this list rather than inventing values; the bot validates against it." }, "status": { "type": "string", "enum": ["unreleased", "released", "hidden"], "description": "unreleased: known but not yet obtainable. released: obtainable and tradeable. hidden: dropped out of matching but retained in inventories, and reversible — most hidden sprites come back." }, "sprite": { "type": "object", "additionalProperties": false, "required": ["base_name", "row_name", "variants"], "properties": { "base_name": { "type": "string", "minLength": 1, "description": "The sprite's base name, shared across its variants. Unique within a season." }, "row_name": { "type": "string", "minLength": 1, "description": "The collection row this sprite belongs to. Autocomplete matches on this as well as base_name." }, "game_mode": { "$ref": "#/$defs/gameMode", "description": "Overrides the season-level game_mode for this sprite only." }, "notes": { "type": "string" }, "variants": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/variant" } } } }, "variant": { "type": "object", "additionalProperties": false, "required": ["variant", "status"], "properties": { "variant": { "type": "string", "minLength": 1, "description": "Variant name, unique within its base sprite. Use \"Default\" when a sprite has only one form." }, "status": { "$ref": "#/$defs/status" }, "released_at": { "type": "string", "format": "date", "description": "ISO 8601 date. Required in practice once status is released; omit while unreleased." }, "max_stack": { "type": "integer", "minimum": 1, "default": 1, "description": "Maximum copies a member can hold. Anything above 1 can enter the give pool as a spare." }, "rarity_weight": { "type": "number", "exclusiveMinimum": 0, "description": "Retained for display and analytics only. The matcher does NOT use it — rarity matching was removed deliberately, because value-matching is how selfish players win and the pool starves." }, "confirmed": { "type": "boolean", "default": false, "description": "Flips true the first time a real member is recorded owning this variant. Unconfirmed entries are deprioritised in autocomplete and excluded from the coverage metric, since variant lists are assumed-complete guesses until proven." }, "notes": { "type": "string" } } } } }