Animal taming
Usage guide of animal.taming: per-handler trust, fear, confirmed feeding and soothing, ownership, bond loss, release and transfer, with settings, commands, events, hooks and presets.
Animal taming (animal.taming) #
What it is for #
Taming rules for a game: each animal keeps a trust value per handler and a fear value. Feeding and soothing raise trust, harm and time lower it, and once a handler’s trust reaches the taming threshold that handler becomes the owner. The game stays authoritative over inventory and the world: an interaction is only a request until the game confirms it.
Turn it on #
gripforge_gamekit_install { project_id: "gkp_…", id: "animal.taming" }
gripforge_gamekit_configure { project_id: "gkp_…", id: "animal.taming", config: { "tameTrust": 0.7, "feedTrust": 0.25 } }
Only the keys that differ from the defaults need to be written. Each animal is one named instance, created by the game; a fresh game already has one instance called default.
First example #
<!-- test: kits/animal_taming/tests/animal_taming.rs::feeding_asks_for_one_item_and_trust_grows_only_when_the_engine_confirms --> A handler feeds a wild animal. The kit asks the game to consume one item; trust grows only when the game confirms with the token (here feedTrust is 0.45).
request ["default", { "op": "interact", "actor": "ann", "kind": "feed", "distance": 1, "visible": true, "safe": true, "alive": true }]
-> { "action": { "kind": "feed", "amount": 1, "token": 1 }, "relationships": { "ann": 0 }, ... }
request ["default", { "op": "resolve", "token": 1, "success": true, "amount": 1 }]
-> { "relationships": { "ann": 0.45 }, "action": null, ... }
Settings and defaults #
| Setting | Default | Meaning |
|---|---|---|
maxHandlers | 16 | Maximum remembered handlers per animal (use forget to free a slot) |
interactionRange | 2 | Maximum observed distance for feeding or soothing |
feedTrust | 0.2 | Trust gained for one confirmed unit of acceptable food |
sootheTrust | 0.05 | Trust gained when a soothing interaction is confirmed |
sootheFear | 0.15 | Fear removed by a confirmed soothing interaction |
tameTrust | 0.8 | Trust that makes a handler the first owner, if the animal has none |
breakTrust | 0.1 | An owner loses the bond when harm brings their trust to this value or below (below tameTrust) |
maxFear | 0.4 | Highest fear that still permits an interaction |
fearDecay | 0.1 | Fear recovered per safe living simulation second |
trustDecay | 0.001 | Trust lost per second by non-owners (an owner’s trust does not decay) |
harmTrust | 0.5 | Trust lost from the reported aggressor at severity 1 |
interactionCooldown | 1 | Minimum seconds between issued interactions, failed attempts included |
receiptTimeout | 2 | Simulation seconds the game has to confirm an interaction |
Commands #
interact { actor, kind, distance, visible, safe, alive } asks for a feed or soothe interaction; it needs range (interactionRange), visibility, safety, a free handler slot and a fear not above maxFear, and answers with an action and a token. resolve { token, success, amount } confirms it: a failed receipt or a zero amount gives nothing, and a receipt that comes after receiptTimeout or for another token is stale. harm { actor, severity } (0 to 1) costs the aggressor trust, raises fear and can break the owner’s bond at breakTrust. step { dt, alive, safe } lets fear and trust decay; danger cancels a pending interaction. The owner can release { actor } the animal or transfer { actor, to } it (the trust goes with the animal); forget { actor } frees a handler slot but never removes the owner. preview, status, config, save and load read and restore; the status holds owner, tamed, fear and the relationships (trust per handler).
Services #
The kit is a driver service: it decides only when the game calls it, never on its own tick.
create(id, config): creates a named instance (config is checked; at most 128 instances; an existing id is refused); returns the id.request(id, command): sends one command object to an instance and returns its answer (unknown instance or invalid command: an error).remove(id): removes an instance; returns whether it existed.ids(): lists the instance ids.
status, config, save, preview and load are reads and state operations; step is the fixed-step command the game sends every tick. Every other command is a decision and goes through the request hook below.
What it announces #
| Name | Detail |
|---|---|
animal.taming.created | An instance was created; payload { instance, preset }. |
animal.taming.removed | An instance was removed; payload { instance }. |
animal.taming.changed | A decision command was applied; payload { instance, op, result }. |
animal.taming.refused | A tap of the request hook cancelled a decision; payload { instance, op, by, reason }. |
Hooks and modding #
A game or a mod taps a hook with a document of its hooks list, without touching the kit:
animal.taming.create: before an instance is created; payload{ instance, preset, config }; a tap may replaceconfig, or cancel (creation then fails withcreation refused).animal.taming.request: before a decision command is applied; payload{ instance, op, command }; a tap may replacecommand, or cancel: the call then answers{ ok: false, cancelled: true, by, reason }and the refused event is emitted.
{ "id": "no_transfer", "hook": "animal.taming.request", "match": { "op": "transfer" }, "cancel": true, "reason": "bound to its owner" }
Presets and scripts #
Presets. A document { "id": "<name>", "config": { … } } in the project data collection animal_taming_presets names a ready-made tuning. create(id, { "preset": "<name>", … }) starts from it; the keys given next to preset win (shallow merge). An unknown preset is an error; the created event carries the preset name.
Scripts and rules can drive an instance with the action animal_taming_request { instance?, command } (instance defaults to default) and test it with the condition animal_taming_exists { instance? }.
When it does not do what you expect #
- Trust does not grow: the interaction was never confirmed (no
resolve, a failed receipt, a zero amount, or a receipt afterreceiptTimeout). - An interaction is refused: check range, visibility,
safe, the cooldown, the fear againstmaxFearand the number of handlers againstmaxHandlers; only the owner canreleaseortransfer.
Limits #
- The kit never touches inventory, food or the world: the game consumes the items and confirms. Ownership is mirrored by the game; trust of a handler fades with time unless the handler is the owner.
- No hidden tick: nothing happens between two
stepcommands, and time passes only by thedtthe game sends. - Instances are saved and restored with the game (including the random generator, so a reload replays the same choices); a pending action must be resolved first.
- Targets: the native kit host and the web player, from the same Rust core. The kit has no display module.
Versions #
1.1.0 (2026-10-19): game.engine hooks, presets, outcome events and script verbs; 1.0.0 (2026-10-16): first release. Requires no other kit.