Research
Usage guide of research.samples: samples studied at a lab, weighted seeded draws of findings that run actions, a codex, settings, service, events, hooks and moddable collections.
Research and discoveries in your game (research.samples) #
What it is for #
research.samples turns items the player brings back into discoveries. A sample is an item of inventory.items; studying one at a lab takes a moment, uses the item up and yields one finding drawn among those the sample can give. A finding is a document: a name, a rarity label and the actions it runs when found (unlock a recipe, a structure, a species, give an item, set a variable, emit an event). The kit knows nothing of what is studied or learned: that belongs to the other kits of the game. A codex keeps what was found and shows the rest as unknown. It suits exploration, archaeology, science, cooking, alien technology and detective games.
Turn it on #
gripforge_gamekit_install { project_id: "gkp_…", id: "research.samples" }
gripforge_gamekit_configure { project_id: "gkp_…", id: "research.samples",
config: { "needsLab": true, "labReach": 5 } }
It requires inventory.items and game.engine, so installing it brings them. Targets: web and the Rust kit host (native player and the engine wrappers).
First example #
<!-- test: kits/game_engine/host/tests/research_samples.rs::a_study_needs_a_lab_and_the_item_then_yields_each_finding_once --> Two collections in the game data, and an inventory.items item shard:
"samples": [ { "id": "shard", "name": "Shard", "item": "shard", "seconds": 0.5, "findings": ["map", "rune"] } ],
"findings": [ { "id": "map", "name": "Map", "weight": 3 }, { "id": "rune", "name": "Rune" } ]
With the default needsLab, study("shard") is refused with reason lab until a lab is open (placeLab then open), then with item while the bag has no shard. With a shard held it answers { ok: true }; a second call answers busy. After 0.5 s research.found fires with one finding. Both findings are found once, so the third study ends with research.nothing, taking its shard.
Settings and defaults #
| Setting | Type | Default | Meaning |
|---|---|---|---|
needsLab | boolean | true | A study needs an open lab. Off: samples are studied anywhere, from the screen the research key opens. |
labReach | number (1 to 30) | 4 | The screen of a lab closes when the player walks further than this many metres. A running study goes on. |
labLabel | string | Use {name} | Prompt of a lab; {name} is its label. |
Input: research_menu (key J) opens or closes the research screen. Without a lab it shows the codex alone, unless needsLab is off.
Data: samples and findings #
A sample (collection samples) has id, name, item (required: one is used up per study), findings (required: ids it can yield; a finding may be listed by several samples), seconds (study length, default 5; 0 is at once), description and fallback (actions run when nothing is left to find).
A finding (collection findings) has id, name (required), description, rarity (a free display label such as common, rare, unique), weight (share of the draw among the findings left, default 1; 0 is never drawn, only granted), once (found a single time, default true; false lets it come again, e.g. a material) and actions run when found.
The draw depends only on the game seed and the number of draws made, so the same game gives the same findings and a loaded game continues as the saved one would have. A finding found in one sample leaves the draws of every sample that lists it.
Lab, service and verbs #
A lab is any entity carrying research.lab ({ label? }): an editor instance with the research_lab component, a placed structure whose components carry research.lab, or placeLab from a script. With interaction.use it offers the labLabel prompt and using it opens the research screen.
Service research.samples:
samples(): the samples withheld,found,totalandexhausted.findings(): the findings withfound(times found).study(id):{ ok, reason? }; reasonsunknown,lab,busy,item.job():{ sample, left, total, ratio }or null.found(finding): times found.grant(finding): counts a finding and runs its actions, no study.open(lab?),close(),current(),placeLab(at, yaw?, label?).
Trigger actions: grant_finding { finding }, study_sample { sample } (one draw at once, as a reward: no lab, no time, no item used). Conditions: finding_found { finding, count? }, sample_exhausted { sample }.
Events and variables #
| Name | Detail |
|---|---|
research.started | { sample, seconds }: one item was taken; the finding comes after seconds. |
research.found | { sample, finding, name, rarity, first }; sample is empty for a grant. first: never found before. |
research.nothing | { sample }: nothing left to find (or a tap cancelled); the sample fallback runs. |
research.failed | { sample, reason }: unknown, item, busy, lab, or the reason of a cancelling tap (refused by default). |
research.opened | { lab }: empty when opened by the key. |
research.closed | The screen closed (key, walked away, game paused, or close()). |
research.open | Variable: the screen is open. |
research.found | Variable (number): distinct findings found. |
research.studying | Variable (string): the sample being studied, empty when none. |
It listens to interaction.requested, entity.spawned and game.phase (the screen closes when the game pauses). The saved state is the count of each finding, the running study and the number of draws.
Hooks and modding #
| Hook | Payload | Mutable | Effect |
|---|---|---|---|
research.study | { sample, item, seconds, lab } | seconds | Before the item is taken. Cancelled: nothing is taken and research.failed carries the tap reason. |
research.find | { sample, finding, rarity, first } | finding | Before a finding is counted. Change finding to another finding id; cancelled: nothing is found (a study ends as research.nothing, a grant answers false). |
{ "id": "quick_ore", "hook": "research.study", "match": { "sample": "ore" }, "mul": { "seconds": 0.5 } }
A mod may override needsLab, labReach and labLabel, and add, patch or remove entries of samples and findings.
When it does not do what you expect #
research.failedwithlab: no lab is open andneedsLabis on; open one or turnneedsLaboff.research.failedwithitem: the bag holds none of the sampleitem.- A finding never comes again:
oncedefaults to true; set"once": false. - A finding never appears: its
weightis 0 (granted only), or no sample lists it.
Limits #
- One study at a time.
- The kit does not define what a finding does: its
actionscall the other kits. - No built-in lab model: provide a
research_labasset.
Versions #
Kit 1.1.1; service research.samples 1.0.0. Hooks and moddable data since 1.1.0 (game.engine 1.2).