{"id":50988143,"url":"https://github.com/devtakkekar/dev-fishing","last_synced_at":"2026-06-19T22:30:38.990Z","repository":{"id":364277396,"uuid":"1267199368","full_name":"devtakkekar/dev-fishing","owner":"devtakkekar","description":"qb-core fishing script","archived":false,"fork":false,"pushed_at":"2026-06-12T12:00:13.000Z","size":24,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-12T12:14:27.921Z","etag":null,"topics":["fishing","fivemresource","lua","oxlib","qbcore-script","script"],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/devtakkekar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-12T10:09:54.000Z","updated_at":"2026-06-12T12:00:23.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/devtakkekar/dev-fishing","commit_stats":null,"previous_names":["devtakkekar/dev-fishing"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/devtakkekar/dev-fishing","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devtakkekar%2Fdev-fishing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devtakkekar%2Fdev-fishing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devtakkekar%2Fdev-fishing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devtakkekar%2Fdev-fishing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/devtakkekar","download_url":"https://codeload.github.com/devtakkekar/dev-fishing/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devtakkekar%2Fdev-fishing/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34550858,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-19T02:00:06.005Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fishing","fivemresource","lua","oxlib","qbcore-script","script"],"created_at":"2026-06-19T22:30:35.169Z","updated_at":"2026-06-19T22:30:38.981Z","avatar_url":"https://github.com/devtakkekar.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"# dev-fishing\n\nPolished, modular fishing script for **QBCore** with an XP leveling system, tiered loot pools, buy/sell peds and dual inventory/target support.\n\n## Features\n\n- 🎣 Equip-to-fish flow: **use the rod to equip it**, then **use bait to cast** - one cast per bait, no AFK loop\n- 📖 **Fish Index** on both peds: undiscovered fish show as `???`; first catches trigger a 'New fish discovery' notify; discovering a full tier awards one-time bonus XP with a 'Completed \u003ctier\u003e' notify\n- 🎮 **Reel-in minigame** on every bite (ox_lib skillCheck by default) - fail and the fish gets away\n- 🔌 **Swappable minigame**: point the config at any resource export, or override at runtime via `exports['dev-fishing']:SetMinigame()`\n- 🧩 Bridges: **qb-inventory / ox_inventory** and **qb-target / ox_target** (`auto` detection or forced via config)\n- 📈 Persistent **XP \u0026 level system** (oxmysql, table auto-created) - higher levels unlock higher loot tiers\n- 🛒 **Buy ped** (fishing shop with quantity input) and 💰 **sell ped** (sell single stacks or everything)\n- 🗂️ **Tiered loot pools** (common / uncommon / rare / legendary) with weighted chances and per-tier level gates\n- 💎 Rare loot: Clam, Treasure Map, Ancient Relic, Lottery Ticket, Fishing Voucher (easy to add more)\n- 📢 Per-item `globalNotify` + customisable `msg`: broadcasts `\u003cplayer name\u003e \u003cmsg\u003e` to all players in chat\n- 🔔 `Config.NotifyXPGain = true`: every catch shows XP earned + updated total\n- ⌨️ `/fishingxp` command: current XP, level and progress to next level\n- 🏆 **Leaderboard**: `/fishingtop` or the shop ped's *Top Anglers* menu (top anglers by XP)\n- 🛠️ **Admin commands**: `/setfishingxp \u003cid\u003e \u003camount\u003e`, `/resetindex \u003cid\u003e`\n- 📡 **Discord webhook logging** for rare catches and big sales (anti-exploit auditing)\n- 📉 **Dynamic market prices**: sell prices fluctuate per restart/interval to discourage botting\n- 🔗 **Server exports**: `GetFishingXP`, `AddFishingXP`, `SetFishingXP`, `GetFishingLevel` for other resources\n- 🌐 **Locale support**: all user-facing text lives in `locales/en.lua`; add `locales/\u003ccode\u003e.lua` and set `Config.Locale`\n- ⛵ **Boat rental ped**: rent a dinghy for a deposit, refunded when the boat is returned to the dock\n- 📊 **`/fishingstats`**: lifetime totals (catches, money earned, rarest catch, best catch streak)\n- 🪝 **Client export** `IsPlayerFishing()`: returns `equipped, casting` for other scripts\n- 🛡️ **Cast position anticheat**: catches are rejected if the player moved too far from where they cast\n- 🔄 **Version checker**: console notice on startup when a newer version is published\n- 🔒 Server-side validation: cast tokens, minimum cast time, catch cooldown, rod/bait ownership, server-priced shop\n\n## Dependencies\n\n- [qb-core](https://github.com/qbcore-framework/qb-core)\n- [ox_lib](https://github.com/overextended/ox_lib)\n- [oxmysql](https://github.com/overextended/oxmysql)\n- qb-inventory **or** ox_inventory\n- qb-target **or** ox_target\n\n## Installation\n\n1. Drop the `dev-fishing` folder into your `resources` directory.\n2. Add `ensure dev-fishing` to your `server.cfg` (after qb-core, ox_lib, oxmysql, your inventory and target).\n3. Add the items below to your inventory system.\n4. Restart the server - the `dev_fishing` SQL table is created automatically.\n\n### qb-core items (`qb-core/shared/items.lua`)\n\n```lua\nfishingrod      = { name = 'fishingrod',      label = 'Fishing Rod',     weight = 2000, type = 'item', image = 'fishingrod.png',      unique = false, useable = true,  shouldClose = true,  description = 'A sturdy fishing rod' },\nfishbait        = { name = 'fishbait',        label = 'Fish Bait',       weight = 50,   type = 'item', image = 'fishbait.png',        unique = false, useable = true,  shouldClose = true,  description = 'Wriggly worms - use to cast your line' },\nanchovy         = { name = 'anchovy',         label = 'Anchovy',         weight = 100,  type = 'item', image = 'anchovy.png',         unique = false, useable = false, shouldClose = false, description = 'A small anchovy' },\nsardine         = { name = 'sardine',         label = 'Sardine',         weight = 100,  type = 'item', image = 'sardine.png',         unique = false, useable = false, shouldClose = false, description = 'A shiny sardine' },\nmackerel        = { name = 'mackerel',        label = 'Mackerel',        weight = 150,  type = 'item', image = 'mackerel.png',        unique = false, useable = false, shouldClose = false, description = 'A striped mackerel' },\nbass            = { name = 'bass',            label = 'Bass',            weight = 250,  type = 'item', image = 'bass.png',            unique = false, useable = false, shouldClose = false, description = 'A decent bass' },\nsalmon          = { name = 'salmon',          label = 'Salmon',          weight = 300,  type = 'item', image = 'salmon.png',          unique = false, useable = false, shouldClose = false, description = 'A fresh salmon' },\ntuna            = { name = 'tuna',            label = 'Tuna',            weight = 500,  type = 'item', image = 'tuna.png',            unique = false, useable = false, shouldClose = false, description = 'A hefty tuna' },\nswordfish       = { name = 'swordfish',       label = 'Swordfish',       weight = 600,  type = 'item', image = 'swordfish.png',       unique = false, useable = false, shouldClose = false, description = 'A mighty swordfish' },\nclam            = { name = 'clam',            label = 'Clam',            weight = 100,  type = 'item', image = 'clam.png',            unique = false, useable = false, shouldClose = false, description = 'Might hold a pearl...' },\ntreasure_map    = { name = 'treasure_map',    label = 'Treasure Map',    weight = 50,   type = 'item', image = 'treasure_map.png',    unique = true,  useable = false, shouldClose = false, description = 'X marks the spot' },\nancient_relic   = { name = 'ancient_relic',   label = 'Ancient Relic',   weight = 400,  type = 'item', image = 'ancient_relic.png',   unique = true,  useable = false, shouldClose = false, description = 'A relic from the deep' },\nlottery_ticket  = { name = 'lottery_ticket',  label = 'Lottery Ticket',  weight = 10,   type = 'item', image = 'lottery_ticket.png',  unique = true,  useable = false, shouldClose = false, description = 'Feeling lucky?' },\nfishing_voucher = { name = 'fishing_voucher', label = 'Fishing Voucher', weight = 10,   type = 'item', image = 'fishing_voucher.png', unique = true,  useable = false, shouldClose = false, description = 'Redeemable for fishing gear' },\n```\n\n### ox_inventory items (`ox_inventory/data/items.lua`)\n\n```lua\n['fishingrod']      = { label = 'Fishing Rod',     weight = 2000, stack = false, close = true },\n['fishbait']        = { label = 'Fish Bait',       weight = 50 },\n['anchovy']         = { label = 'Anchovy',         weight = 100 },\n['sardine']         = { label = 'Sardine',         weight = 100 },\n['mackerel']        = { label = 'Mackerel',        weight = 150 },\n['bass']            = { label = 'Bass',            weight = 250 },\n['salmon']          = { label = 'Salmon',          weight = 300 },\n['tuna']            = { label = 'Tuna',            weight = 500 },\n['swordfish']       = { label = 'Swordfish',       weight = 600 },\n['clam']            = { label = 'Clam',            weight = 100 },\n['treasure_map']    = { label = 'Treasure Map',    weight = 50,  stack = false },\n['ancient_relic']   = { label = 'Ancient Relic',   weight = 400, stack = false },\n['lottery_ticket']  = { label = 'Lottery Ticket',  weight = 10,  stack = false },\n['fishing_voucher'] = { label = 'Fishing Voucher', weight = 10,  stack = false },\n```\n\n\u003e **Note (ox_inventory):** `QBCore.Functions.CreateUseableItem` works through the qb bridge. If you run ox_inventory standalone, add `server = { export = 'dev-fishing.useRod' }`-style hooks or keep the qb bridge enabled.\n\n## Configuration\n\n| File | Purpose |\n|---|---|\n| `config/config.lua` | Bridges, items, timings, rod break chance, XP levels, `NotifyXPGain` |\n| `config/loot.lua` | Loot tiers, weights, level gates, XP/prices, `globalNotify` + `msg` per item |\n| `config/peds.lua` | Buy/sell ped models, coords, blips and the shop catalogue |\n\n### Minigame\n\nWhen a fish bites, a reel-in minigame runs. Failing it means the fish gets away (bait is still consumed).\n\n```lua\nConfig.Minigame = {\n    enabled = true,\n    type = 'skillcheck',                       -- built-in ox_lib skillCheck\n    difficulty = { 'easy', 'easy', 'medium' },\n    keys = { 'w', 'a', 's', 'd' },\n    custom = { resource = '', export = '' },   -- use another resource's minigame export\n}\n```\n\n**Use a different minigame** (no code changes needed) - any export that returns `true` on success works:\n\n```lua\ncustom = { resource = 'ps-ui', export = 'Circle' }\n```\n\n**Override at runtime** from any other resource:\n\n```lua\n-- in your own resource (client-side)\nexports['dev-fishing']:SetMinigame(function()\n    return exports['my-minigames']:keypad({ difficulty = 'hard' })\nend)\n\n-- restore the config-driven default\nexports['dev-fishing']:ResetMinigame()\n```\n\nThe minigame function must block until finished and return `true` for success.\n\n### Adding a rare item with a global chat broadcast\n\n```lua\n{\n    item = 'golden_hook', label = 'Golden Hook', weight = 10, xp = 100, price = 0,\n    globalNotify = true,                                  -- broadcast to all players\n    msg = 'fished up the legendary Golden Hook!',          -- customisable message\n},\n```\n\nBroadcast format in chat: `🎣 Lucky Catch | \u003cFirstname Lastname\u003e \u003cmsg\u003e`\n\n## Usage\n\n- Buy a rod + bait from the **Fishing Shop** ped.\n- **Use the rod** to equip it (use it again to pack up).\n- Stand facing open water and **use bait** to cast - each cast consumes 1 bait.\n- When a fish bites, beat the reel-in minigame to land the catch.\n- First-time catches are logged in the **Fish Index** (available on both peds); discover every fish in a tier for one-time bonus XP.\n- Sell your catches at the **Fish Buyer** ped (single stacks or everything).\n- Check progress with `/fishingxp`.\n\n## Commands\n\n| Command | Permission | Description |\n|---|---|---|\n| `/fishingxp` | everyone | Current XP, level and progress to next level |\n| `/fishingtop` | everyone | Leaderboard of top anglers by XP |\n| `/fishingstats` | everyone | Lifetime stats: catches, money earned, rarest catch, best streak |\n| `/setfishingxp \u003cid\u003e \u003camount\u003e` | admin | Set a player's fishing XP |\n| `/resetindex \u003cid\u003e` | admin | Wipe a player's fish index discoveries |\n\n## Exports (server)\n\n```lua\nlocal xp = exports['dev-fishing']:GetFishingXP(citizenid)\nlocal newXP = exports['dev-fishing']:AddFishingXP(citizenid, 50)\nexports['dev-fishing']:SetFishingXP(citizenid, 500)\nlocal level, rank = exports['dev-fishing']:GetFishingLevel(citizenid) -- e.g. 3, 'Skilled'\n```\n\nClient-side:\n\n```lua\nlocal equipped, casting = exports['dev-fishing']:IsPlayerFishing()\n```\n\n## Webhook \u0026 market\n\n```lua\nConfig.Webhook = {\n    enabled = false,\n    url = '',                -- Discord webhook URL\n    logAllCatches = true,    -- logs every catch (item + XP gained + total XP)\n    logRareCatches = true,   -- logs globalNotify catches even if logAllCatches = false\n    logAllSales = true,      -- logs every sale at the sell ped\n    bigSaleThreshold = 1000, -- highlights sales \u003e= $1000 (0 = no highlight)\n}\n\nConfig.DynamicPrices = {\n    enabled = true,\n    variance = 15, -- sell prices vary +/- 15% around the base price\n    interval = 60, -- market refreshes every 60 minutes and on restart\n}\n```\n\n## Localization\n\nAll user-facing strings live in `locales/en.lua`. To add a language:\n\n1. Copy `locales/en.lua` to e.g. `locales/de.lua` and change `Locales['en']` to `Locales['de']`.\n2. Translate the values (keep the `%s` / `%d` placeholders intact).\n3. Add the file to `shared_scripts` in `fxmanifest.lua` and set `Config.Locale = 'de'`.\n\nMissing keys automatically fall back to English.\n\n## SQL\n\nThe table is created automatically, but for reference:\n\n```sql\nCREATE TABLE IF NOT EXISTS `dev_fishing` (\n    `citizenid` VARCHAR(64) NOT NULL,\n    `xp` INT UNSIGNED NOT NULL DEFAULT 0,\n    `discovered` LONGTEXT NULL,\n    PRIMARY KEY (`citizenid`)\n);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevtakkekar%2Fdev-fishing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevtakkekar%2Fdev-fishing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevtakkekar%2Fdev-fishing/lists"}