# Packs and collection (collection.packs) ## What it is for Packs to buy and open and a collection to complete. Packs, collectibles and rarities are data: a pack has a price, a number of objects, odds by rarity, guaranteed slots, pity timers and the sets it draws from. Opening a pack draws its objects with a numbered, deterministic fork of the game's random generator; the objects enter the collection at once and are revealed one by one. An album shows what is owned and the completion of each set; duplicates are refunded, kept or discarded. It pays through `economy.money` when present, sells packs at a `trade.shop` counter and hands cards to `cards.deck`. ## Turn it on ```text gripforge_gamekit_install { project_id: "gkp_…", id: "collection.packs" } gripforge_gamekit_configure { project_id: "gkp_…", id: "collection.packs", config: { "starterPacks": ["starter_pack"], "duplicates": "refund" } } ``` Only `game.engine` is required. Without `economy.money` only free packs can be bought and duplicates are kept. The three collections are documents of your game: ```json { "rarities": [ { "id": "common", "refund": 5 }, { "id": "rare", "refund": 40 } ], "collectibles": [ { "id": "moss_hare", "rarity": "common", "set": "beasts" }, { "id": "glass_owl", "rarity": "rare", "set": "beasts" } ], "packs": [ { "id": "starter_pack", "price": 100, "count": 3, "odds": { "common": 9, "rare": 1 }, "guaranteed": [ { "rarity": "rare", "min": 1 } ] } ] } ``` ## First example The replayed fixture grants starter packs, buys one, opens it, reveals the objects and reads the album: ```text collection.packs.buy("starter_pack") -> pack.bought { pack, price, owned } collection.packs.grant("starter_pack", 3, "gift") -> pack.granted collection.packs.open("starter_pack") -> pack.opened { items: [ { collectible, rarity, new } ... ] } collection.packs.reveal() -> pack.revealed (the next object at once) collection.packs.progress() -> { owned, total, percent } ``` A refused call emits `pack.refused` with `unknown`, `too_poor`, `no_wallet`, `none_left`, `busy`, `empty` or the reason of a tap. ## Settings and defaults | Setting | Default | Meaning | |---|---|---| | `payment` | `money` | `money`: a pack costs its price through `economy.money`; `free`: every pack is free | | `duplicates` | `refund` | `refund` (money, kept if no `economy.money`), `keep` (counted in the album) or `discard` | | `revealEvery` | 0.9 | seconds between two revealed objects (0: all at once) | | `starterPacks` | `[]` | pack ids granted once at the start (repeat an id for several) | | `deckGrant` | `false` | with `cards.deck`: a drawn collectible that names a `card` adds it to the deck | | `shop` | `true` | the kit sells its packs itself (the Packs screen); off: packs come from `grant`, a shop counter or a script | | `albumKey` | `true` | the keys that open the album (C) and the packs screen (P) | Pack fields: `price`, `count` (1 to 50), `odds` (rarity to weight), `guaranteed` (`rarity`, `min`), `pity` (`rarity`, `every`), `sets`, `cover`. Collectible fields: `rarity`, `set`, `image`, `card`, `refund`, `tags`. ## Services, events, variables - `collection.packs` (service): `packs()`, `collectibles()`, `rarities()`, `wallet()`, `buy(pack)`, `grant(pack, n, reason)`, `open(pack)`, `opening()`, `reveal()`, `close()`, `owned(collectible)`, `unopened()`, `progress()`, `show(screen)`, `screen()`. - Events: `pack.bought`, `pack.granted`, `pack.refused`, `pack.opened`, `pack.revealed`, `pack.closed`, `collection.added`, `collection.duplicate`, `collection.progress`, `collection.set_completed`, `collection.completed`, `collection.screen`; it listens to `shop.bought`. - Variables: `collection.owned`, `collection.total`, `collection.percent`, `collection.packs`, `collection.opening`, `collection.screen`. - Content verbs: `grant_pack`, `open_pack` (actions), `collection_has`, `collection_complete` (conditions). ## Hooks and modding | Hook | Mutable | Asked | |---|---|---| | `pack.buy` | `price` | before the balance check; cancelling refuses with the reason of the tap | | `pack.open` | `count` | before an unopened pack is opened; cancelling keeps it closed | | `pack.draw` | `collectible` | for each drawn object; cancelling drops that slot | | `collection.duplicate` | `refund` | before a duplicate is refunded; cancelling keeps it in the album | A hook never draws a random number. The registries `rarities`, `packs` and `collectibles` are moddable (a document with `extends` makes a variant, such as a holiday pack with better odds), and so are all the settings. ## Limits The album and the opening are drawn by the kit's view; other engines show them through `ui.webui`. Odds are weights on any scale: a rarity with no collectible in the pool of a pack is never drawn. Runs on the web and in the native player. ## Versions Kit 1.0.0 and service `collection.packs` 1.0.0.