# Fishing (fishing.rod) ## What it is for Lets the player cast a line over water, strike when a fish bites and reel it in without snapping the line, with the catch drawn from a fish table by zone, hour, weather and rarity. It needs `input.actions`, `game.engine`; installing it brings them in. ## Turn it on Install the kit in a project, then change a setting (the values shown are its defaults): ```text gripforge_gamekit_install { project_id: "gkp_…", id: "fishing.rod" } gripforge_gamekit_configure { project_id: "gkp_…", id: "fishing.rod", config: { "rodItem": "fishing_rod", "baitItem": "" } } ``` ## First example This is the body of the passing test `a_cast_bites_is_struck_and_reeled_in`; the helper functions it calls are defined at the top of the same test file. ```rust #[test] fn a_cast_bites_is_struck_and_reeled_in() { let mut s = session(); assert_eq!( call(&mut s, "cast", json!([])), json!({ "ok": false, "reason": "player" }) ); s.apply(&json!({ "op": "create", "kind": "player", "tags": ["player"], "components": { "transform": { "x": 0, "y": 0, "z": 0, "yaw": 0 } } })) .unwrap(); assert_eq!( call(&mut s, "cast", json!([])), json!({ "ok": false, "reason": "water" }) ); call(&mut s, "placeSpot", json!(["pond", [0, 0, 6], 3])); assert_eq!(call(&mut s, "zoneHere", json!([])), json!(["pond"])); assert_eq!( call(&mut s, "table", json!(["pond"])), json!([{ "id": "carp", "name": "Carp", "rarity": "common", "chance": 1 }]) ); assert_eq!(call(&mut s, "cast", json!([])), json!({ "ok": true })); step(&mut s, 31); // The var keeps `waiting` through the bite (the web runtime publishes on the strike, not on the bite). assert_eq!(s.host.state.get("fishing.state"), Some(&json!("waiting"))); assert_eq!(call(&mut s, "state", json!([]))["state"], json!("bite")); assert_eq!(call(&mut s, "hook", json!([])), json!(true)); call(&mut s, "reel", json!([true])); step(&mut s, 31); assert_eq!(s.host.state.get("fishing.state"), Some(&json!("idle"))); assert_eq!(call(&mut s, "catches", json!([])), json!({ "carp": 1 })); s.apply(&json!({ "op": "save" })).unwrap(); s.apply(&json!({ "op": "reload" })).unwrap(); assert_eq!(s.host.state.get("fishing.caught"), Some(&json!(1))); } ``` ## Settings and defaults Descriptions come from the kit manifest and stay in English. | Setting | Type | Default | Range or values | Meaning | |---|---|---|---|---| | `rodItem` | string | `"fishing_rod"` | | Item the player must hold to cast (empty: none needed). | | `baitItem` | string | `""` | | Item taken at every cast (empty: no bait). | | `castDistance` | number | `6` | 1–40 | How far ahead the float lands. | | `biteMin` | number | `3` | 0.2–120 | Shortest wait before a bite (s). | | `biteMax` | number | `9` | 0.2–300 | Longest wait before a bite (s). | | `biteWindow` | number | `1.2` | 0.1–10 | Seconds to strike once it bites. | | `tensionRise` | number | `0.6` | 0.01–5 | Tension added per second while reeling (plus the fish pull). | | `tensionFall` | number | `0.5` | 0.01–5 | Tension lost per second when not reeling (minus the fish pull). | | `startTension` | number | `0.4` | 0–0.95 | | | `reelRate` | number | `0.3` | 0.01–5 | Progress per second while reeling, divided by the fish difficulty. | | `slipRate` | number | `0.1` | 0–5 | Progress lost per second when not reeling. | | `slackSeconds` | number | `1.5` | 0.1–10 | A line slack (tension 0) this long lets the fish go. | | `moveLimit` | number | `3` | 0.5–20 | Walking this far from where you cast reels the line in. | | `rarityWeights` | object | `{"common": 60, "uncommon": 25, "rare": 10, "l…` | | rarity → weight of a fish without its own weight (default common 60, uncommon 25, rare 10, legendary 3). | ## Services, events, variables - Service `fishing.rod`: cast() → { ok, reason? }, hook(), reel(on), cancel(), state(), table(zone, hour?, weather?), zoneHere(), catches(), spots(). - Events emitted: - `fishing.cast` (`zone`) - `fishing.bite` (`zone`) — Strike within biteWindow. - `fishing.hooked` (`fish`, `rarity`) - `fishing.caught` (`fish`, `item`, `rarity`, `size`, `stored`) - `fishing.lost` (`reason`, `fish`) - Variables: - `fishing.state` (string) — Fishing state - `fishing.tension` (number) — Line tension - `fishing.progress` (number) — Reel progress - `fishing.caught` (number) — Fish caught - Verbs of the scripting layer: - `place_fishing_spot` (action) — Mark water to fish in. - `fish_caught` (condition) — That many of this fish (any fish when absent) were caught. - Input actions: `fish` ## Hooks and modding - Hooks (a game or a mod can intercept them): - `fish.cast` (cancellable) — The line is about to be cast over zone (rod held, water under the float; asked before the bait is taken and before the wait is drawn). - `fish.bite` (fields a tap may change: `fish`, `window`; cancellable) — The wait is over and fish was drawn: it is about to bite. - `fish.catch` (fields a tap may change: `item`, `size`; cancellable) — The reel is complete and the size was drawn: fish is about to be landed and given as item (a trophy size, another reward). - Moddable settings: `rodItem`, `baitItem`, `castDistance`, `biteMin`, `biteMax`, `biteWindow`, `tensionRise`, `tensionFall`, `startTension`, `reelRate`, `slipRate`, `slackSeconds`, `moveLimit`, `rarityWeights` - Moddable collections: `fish` - Components: `fishing_spot` ## Engines Declared targets: `web`, `rust`. `gripforge kit api fishing.rod` lists the exact settings and services of your version. ## Versions Kit version 1.1.0.