# 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 ```text 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 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). ```text 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 replace `config`, or cancel (creation then fails with `creation refused`). - `animal.taming.request`: before a decision command is applied; payload `{ instance, op, command }`; a tap may replace `command`, or cancel: the call then answers `{ ok: false, cancelled: true, by, reason }` and the refused event is emitted. ```json { "id": "no_transfer", "hook": "animal.taming.request", "match": { "op": "transfer" }, "cancel": true, "reason": "bound to its owner" } ``` ## Presets and scripts Presets. A document `{ "id": "", "config": { … } }` in the project data collection `animal_taming_presets` names a ready-made tuning. `create(id, { "preset": "", … })` 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 after `receiptTimeout`). - An interaction is refused: check range, visibility, `safe`, the cooldown, the fear against `maxFear` and the number of handlers against `maxHandlers`; only the owner can `release` or `transfer`. ## 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 `step` commands, and time passes only by the `dt` the 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.