Koja Scripts

Configuration

Every option in the Koja Fishing config files and the in-game admin panel: minigame, guide, fish, items, spots, peds, quests, tournaments, licence, boats, diving, digging, poaching, party, translations and skills.

Configuration

Every setting of Koja Fishing lives in shared/, split into one file per system. This page walks through each file and says what every option does. The skill tree is configured separately in data/skills.json.

FileWhat it controls
config.main.luaLanguage, debug, levels, security, shop limits, dynamic prices, redeem codes, electric fishing.
config.minigame.luaCast and stop keys, the strike window and the reeling fight per rarity.
config.tutorial.luaThe fishing guide: guide ped, starter kit, reward, cutscene shots.
config.admin.luaWho can open the in-game admin panel.
config.fish.luaEvery fish species, equipment tiers, level gates, protected species.
config.items.luaRods, reels, lines, baits, accessories, treasures, their stats, prices and required levels.
config.spots.luaFishing spots, their requirements, fish lists and boosted zones.
config.peds.luaNPCs: guide, shops, quests, tournaments, boat rental, licence exam, diving, digging, hermits.
config.hotbar.luaThe equipment hotbar and its key.
config.quests.luaQuest boards, objectives and rewards.
config.tournaments.luaScheduled and automatic tournaments, prizes.
config.test.luaThe fishing licence exam and its lessons.
config.boatrent.luaRentable boats and the anchor key.
config.diving.luaDiving caches, scuba gear, the first-dive tutorial and diving contracts.
config.digging.luaDigging, the digging tutorial, the bike, digging gear and contracts.
config.poaching.luaProtected spots and species, police inspections and fines.
config.party.luaFishing parties, shared sales and group goals.

config.main.lua

shared/config.main.lua
Config.Locale = 'en'
Config.Debug = false
Config.ChanceToRodDamage = 15
Config.CreateAutoTable = true
Config.StartingValues = { level = 1, exp = 0 }
KeyWhat it does
Config.LocaleLanguage of notifications, the whole UI and the translated content: pl, en, de, es, fr, it, pt, cs, ru or tr (locales/<locale>.json). Missing keys fall back to Polish.
Config.DebugConsole logs and debug commands (/battery, /divingtest, /rewardtest, /digprop, kf_levelup_preview). Turn it off on a live server.
Config.ChanceToRodDamageChance in % that a lost fight (snapped line or escaped fish) also destroys the rod. The Rod care skill lowers it.
Config.CreateAutoTableCreates and migrates database tables on start.
Config.StartingValuesLevel and XP of a new angler.

Levels

Config.MaxLevel = 30
Config.ExpBase = 100
Config.ExpGrowth = 20

The XP needed to go from level n to n + 1 is ExpBase + (n - 1) * ExpGrowth. Each level gained grants skill points (sp_per_level in data/skills.json). XP stops at the last level.

Security

Config.Security = {
    ValidatePedDistance = true,
    PedInteractDistance = 10.0,
    OnSuspicious = function(source, reason)
    end,
}
KeyWhat it does
ValidatePedDistanceThe server rejects shop, tournament and licence exam requests from players who are not next to the matching ped. Boat rental, the guide, diving and digging use their own fixed radius.
PedInteractDistanceMaximum distance in metres to the ped.
OnSuspiciousCalled on the server for every rejected cheat attempt. Plug in your anticheat, ban system or a webhook here.

See Security for what is validated.

Shop and dynamic prices

Config.Shop = { MaxQuantityPerItem = 100 }

Config.PriceChange = {
    enabled = true,
    changeInterval = 7200,
    maxItemsToChange = 8,
}
KeyWhat it does
Shop.MaxQuantityPerItemLargest quantity of one item in a single buy or sell.
PriceChange.enabledPuts random items on sale.
PriceChange.changeIntervalSeconds between price rolls.
PriceChange.maxItemsToChangeHow many items are discounted at a time.

A discounted item costs between price - maxPriceChange and price (see items). Shop peds can change prices with their own multipliers (see peds).

Redeem codes

Config.RedeemCode = {
    enabled = true,
    createCommand = 'createfishingcode',
}

Codes give a temporary luck bonus and are entered in the shop. Each player can use a code once. Create codes from the server console — see Commands.

Electric fishing

Config.BatteryElectric tunes the illegal battery method.

KeyWhat it does
placeDurationMs, connectDurationMs, activateDurationMsProgress bar length for placing the battery, connecting the cable, starting it.
activateSkillCheck, activateSkillCheckDifficulty, activateSkillCheckKeysBuilt-in skill check when starting the battery: on or off, the difficulty of each round and the keys used.
cycleDurationMsHow long one battery cycle lasts.
firstEmergeDelayMs, emergeIntervalMsDelay before the first fish and between fish.
fishCountMin, fishCountMax, maxFishPerCycleFish per cycle (skill klusownik_battery_yield adds on top).
catchChanceMin, catchChanceMaxChance range in % to grab a stunned fish. A failed grab loses that fish.
collectMinigame, minigameDurationMsShort minigame when grabbing a fish.
interactionModeox_target, or drawtext (3D text, key drawTextControl, range drawTextInteractDistance).

Every grabbed fish counts as poaching evidence — see config.poaching.lua.

config.minigame.lua

Keys, the strike window and the reeling fight.

shared/config.minigame.lua
Config.Minigame = {
    CastKey = 'E',
    CancelKey = 'X',
    DuiHeight = 1.35,
    DuiSize = 0.85,
    HookWindowMs = 1800,
    DirectionChange = { min = 1600, max = 3400 },
    DirectionWarningMs = 650,
    TensionGraceSeconds = 0.4,
    StartDistance = { min = 11.0, max = 16.0 },
    MaxDistance = 24.0,
}
KeyWhat it does
CastKey / CancelKeyDefault keys of kf_cast and kf_cancel (FiveM key names). Players can rebind them in Settings → Key Bindings → FiveM.
DuiHeight / DuiSizeHeight above the player and size, in metres, of the in-world fishing indicator.
HookWindowMsTime to click after the bite before the fish escapes.
DirectionChangeRandom time in ms between changes of the side the fish pulls to.
DirectionWarningMsHow long before a side change the warning shows.
TensionGraceSecondsSeconds the line can stay at 100% tension before it snaps.
StartDistanceDistance in metres of the fish when the fight starts.
MaxDistanceThe fish escapes when it gets this far away.
RodDamageDamage roll per rarity sent to the server when a fight is lost; the server then breaks the rod with the Config.ChanceToRodDamage chance.
RarityFight balance per rarity, see below.

Every value in Rarity.<rarity> is a rate per second:

KeyWhat it does
reelSpeedMetres reeled in while holding left mouse.
fishPullMetres the fish swims away while you are not reeling.
reelTension / relaxTensionTension added while reeling / removed while not reeling.
wrongTensionExtra tension while holding the wrong side key, or both.
counterReliefTension removed while holding the correct side key.
driftSpeedSide drift when not countering. The line snaps when the drift reaches the edge.
burstChance / burstTensionChance of a sudden run, and extra tension while reeling during a run.

config.tutorial.lua

The fishing guide for new anglers.

shared/config.tutorial.lua
Config.Tutorial = {
    Enabled = true,
    GuidePed = 'kuba',
    InviteNewPlayers = true,
    InviteDistance = 60.0,
    StarterKit = {
        { name = 'fishing_rod', count = 1 },
        { name = 'basic_reel', count = 1 },
        { name = 'basic_line', count = 2 },
        { name = 'worm_bait', count = 15 },
    },
    SkillPed = 'angelo',
    RewardXp = 50,
    BookItem = 'fishpedia',
    FishingPoint = vector3(-1847.0, -1250.8, 13.0),
}
KeyWhat it does
EnabledTurns the guide on.
GuidePedKey of the guide ped in Config.Peds (pedtype = 'guide').
InviteNewPlayers / InviteDistanceAnglers who have not finished the guide see a marker above the guide and get a hint within this distance.
StarterKitItems given once per character when the guide starts.
SkillPedPed the "unlock your first skill" step points to.
RewardXpXP given once when the guide is finished.
BookItemUsable item given at the end (and again by the guide when the player lost it). Using it opens the Fishpedia. false disables it.
FishingPointWaypoint of the "go to the water" step. Any fishing spot completes the step.
CutsceneShots of the intro tour, see below.

Each Cutscene entry is one shot:

FieldWhat it does
pedPed key. The camera is placed in front of the ped's first zone: distance metres in front, side metres to its right, height above its feet, aiming at lookHeight.
coords / offsetInstead of ped: a world position and the camera offset from it.
fovCamera field of view.
durationShot length in ms.
title / textLocale keys of the caption.

config.admin.lua

The in-game admin panel edits config values live and stores them in the koja-fishing-config table.

shared/config.admin.lua
Config.Admin = {
    Enabled = true,
    Command = 'fishingadmin',
    Ace = 'koja-fishing.admin',
    Groups = { 'admin', 'superadmin' },
}
KeyWhat it does
EnabledTurns the panel and its command on.
CommandChat command that opens the panel.
AceACE permission that allows the panel (add_ace group.admin koja-fishing.admin allow).
GroupsFramework groups that can use the panel without the ACE permission.

The panel groups its sections into Gameplay, Content, World and System:

SectionEdits
GeneralLocale, ChanceToRodDamage, MaxLevel, ExpBase, ExpGrowth, StartingValues, Shop, PriceChange, RedeemCode, Security, Hotbar.
Minigame, Tutorial, BatteryConfig.Minigame, Config.Tutorial (with cutscene shots), Config.BatteryElectric.
Fish, ItemsConfig.Fish with RarityMinLevel, Config.Items with EquipmentTiers.
Spots, Bubble zonesConfig.Spots, BoostedZonesSettings, and the boosted zones of every spot. You can also activate a chosen zone right away.
Peds, Boat rental, Digging, DivingConfig.Peds, Config.Rent, Config.Digging, Config.Diving.
Quests, Tournaments, Licence examConfig.Quests, Config.Tournaments, Config.Test (with questions).
PlayersOnline players and offline lookup by identifier: grant or revoke the licence, reset exam attempts, add XP (online only), add skill points, set the level.

Items and fish use a list and detail editor: you can add an entry from a template or as a copy, delete it and restore a deleted file entry. Entries added in the panel live in the database; their key must be 2–40 characters of a-z, 0-9 and _. Spots, peds, quest boards, exam questions, boats, diving caches and cutscene shots use the same editor without adding or deleting.

Config.Admin, Config.Debug, Config.CreateAutoTable, Config.Poaching, Config.Party, the generated level table and functions such as OnSuspicious stay file-only.

config.fish.lua

Each fish is an entry in Config.Fish, keyed by its item name:

shared/config.fish.lua
['swamp_catfish'] = {
    name = 'Swamp Catfish',
    description = 'A huge catfish from the Zancudo marshes. Protected species.',
    rarity = 'uncommon',
    protected = true,
    weight = { min = 6.0, max = 18.0 },
    sellPrice = 260,
    xp = 30,
    length = { min = 70, max = 130 },
    image = 'swamp_catfish.webp',
    sellable = true,
    requirements = {
        minRodTier = 2,
        minLineTier = 2,
        minBaitTier = 1,
    },
},
FieldWhat it does
raritycommon, uncommon, rare or legendary. Drives quality, level gate, fight difficulty and boosted zone odds.
weightWeight range in kg. The line must hold this weight.
lengthLength range in cm, shown on the catch screen.
sellPricePrice for an average-weight fish. Heavier fish are displayed as worth more; the shop pays sellPrice per fish plus trader skill bonuses.
xpXP for releasing the fish.
requirementsMinimum tier of rod, line and bait (Config.EquipmentTiers).
minLevelOptional. Overrides the rarity level gate.
mustReleaseOptional. The fish is never rolled.
sellable = falseThe shop refuses to buy it.
protectedOptional. Protected species: carrying it is evidence for the police, see config.poaching.lua.

Config.RarityMinLevel sets the level an angler needs for each rarity (common = 1, uncommon = 5, rare = 15, legendary = 24). Config.EquipmentTiers maps every rod, line, bait and reel to a tier from 1 to 5.

Names and descriptions are translated from the locales (game.content.fish.<key>.name / .description); the config text is the fallback.

config.items.lua

Equipment, accessories and treasures, keyed by item name:

shared/config.items.lua
['advanced_rod'] = {
    name = 'Advanced Rod',
    requiredLevel = 3,
    price = 500,
    maxPriceChange = 100,
    sellPrice = 375,
    stats = { castDistance = 50.0, catchBonus = 10, durability = 150 },
    category = 'equipment',
    quality = 'uncommon',
},
FieldWhat it does
requiredLevelFishing level from which the shop sells the item. The level-up screen lists gear unlocked at the new level.
priceShop price. Items without a price (or price = 0) cannot be bought.
maxPriceChangeLargest discount during a price roll.
sellPriceWhat the shop pays back.
statsRods: catchBonus, durability. Reels: biteChance, waitTimeReduction (seconds off the bite wait). Lines: maxFishWeight, tensionResistance. Baits: catchBonus, rareFishBonus. Necklaces: luckBonus.
categoryShop category: equipment, baits, accessories, treasure or other.
qualityQuality shown in the shop and used by its quality filter.

Treasures (pearl, ancient_coin, sunken_compass, ship_bell, pirate_doubloon, rusty_key, fossil_shell, amber_chunk) have price = 0: they come from diving and digging and can only be sold.

Accessories work from the inventory: the best luckBonus necklace a player carries is applied automatically.

config.spots.lua

A player can only fish inside a spot.

shared/config.spots.lua
{
    id = 'cassidy_creek',
    name = 'Cassidy Creek',
    description = 'A clear forest river full of trout. Licence and an Advanced Rod required.',
    hidden = { enable = false },
    requiredLevel = 3,
    requireLicense = true,
    minRodTier = 2,
    locationType = 'radius',
    radius = { coords = vector3(-1651.7494, 4451.0513, 4.7721), range = 85.0 },
    fish = {
        { name = 'trout', chance = 40 },
        { name = 'rainbow_trout', chance = 25 },
    },
    waitTimeModifier = 0.95,
    blip = { enabled = true, sprite = 68, color = 25, label = 'Cassidy Creek', minLevel = 3 },
},
FieldWhat it does
idUnique id. Quest objectives filter on it with spot.
name / descriptionShown when the player enters the spot.
requiredLevelAngler level needed to fish here.
requireLicenseOptional. Only anglers with a fishing licence can fish here.
minRodTierOptional. Minimum rod tier from Config.EquipmentTiers.rods (2 = Advanced Rod).
unlockFlagOptional. Fishing needs this unlock, for example hermit_cave from Tom's quest (see Exports).
protectedOptional. Fishing here is poaching: catches are recorded as evidence and can alert the police.
radiusCentre and radius of the spot. Only locationType = 'radius' is supported.
fishWeighted fish list. Without a list the spot rolls by rarity from all fish, using bait, reel and luck bonuses.
waitTimeModifierMultiplies the bite wait.
boostedZonesCandidate bubble zones.
boostedFishExtra multiplier for specific fish inside an active boosted zone.
hiddenHidden spot: no blip, a networked prop marks it.
blipMap blip for the spot. minLevel shows the blip only from that fishing level.

All requirements are checked by the server when the cast starts.

Config.BoostedZonesSettings controls the bubble event: one zone on the map is active for activeDurationSeconds, then the system waits cooldownSeconds and picks another. Inside it, rarityMultipliers change the odds per rarity.

config.peds.lua

shared/config.peds.lua
['hank'] = {
    name = 'Hank',
    model = 'a_m_m_hillbilly_01',
    pedtype = 'shop',
    icon = 'fa-solid fa-store',
    licenserequired = false,
    scenario = 'WORLD_HUMAN_LEANING',
    shop = {
        buyMultiplier = 0.85,
        sellMultiplier = 1.15,
    },
    zones = {
        { coords = vector4(1302.5378, 4226.6919, 33.9087, 75.7342) },
    },
    blip = { enabled = true, sprite = 52, color = 3 },
},
FieldWhat it does
pedtypeguide, shop, quest, tournament, boat_rental, test (licence exam), diving, digging or hermit.
zonesOne or more positions. Each zone spawns the ped. A zone can set its own waypoint for info peds, and the digging ped's zone can set bikeSpawn.
licenserequiredThe ped only talks to players with a fishing licence.
scenarioGTA scenario the ped plays. Instead you can use anim = { dict, name } and prop = { model, bone, offset, rotation }.
iconox_target icon.
blipMap blip. The label is translated from game.peds.<pedtype>; set blip.label to override it.
shopShop peds only. buyMultiplier and sellMultiplier change this ped's prices.
info.waypointDiving and digging peds. Point marked by the Mark on map button at the first zone, also used by the digging tutorial. Diving falls back to the middle of Config.Diving.Props.
hermitHermit peds. storyParagraphs and a quest with id, requirements (item, count) and reward (xp, money, items, unlock). Texts come from game.content.hermits.<key>.*.

Most default peds have a second zone on Chumash Pier. Hank runs a village shop at the Alamo Sea; the hermits Tom and Gustaw have no blip.

The server measures distance to these zones, so a ped you remove here can no longer be used from anywhere.

config.hotbar.lua

The hotbar is where the angler equips gear before casting.

KeyWhat it does
OpenCommand / OpenKeyCommand (kf_hotbar_open) and default key (Q) that open the hotbar. Players can rebind it in GTA key settings.
CommandDescriptionLabel of the key binding in the GTA settings.
SlotsThe four slots — rod, reel, line, bait — and which items fit each. All four must be filled to fish.

config.quests.lua

Quests are grouped in boards. With AutoUnlockNextBoard = true each board unlocks when the previous one is complete, and quests in a board are done in order.

shared/config.quests.lua
{
    id = 4,
    name = 'Angler’s Path',
    description = 'Prove yourself on the river and earn a master’s rod.',
    image = './images/quests/quests_legal.webp',
    type = 'main',
    independent = true,
    quests = {
        { id = 31, title = 'Catch 5 trout at Cassidy Creek', objective = {
            label = 'Caught', target = 5,
            type = 'catch', item = 'trout', spot = 'cassidy_creek',
        }, reward = { xp = 150, money = 500 } },
        { id = 33, title = 'Sell 15 fish', objective = {
            label = 'Sold', target = 15, type = 'sell',
        }, reward = { xp = 250, items = { { name = 'master_rod', count = 1 } } } },
    },
},
Board fieldWhat it does
typemain or side — the page of the quest window the board is shown on.
independentThe board is available from the start, in parallel with other boards, and does not block the chain.
name, descriptionBoard texts, translated from game.content.quests.boards.b<id>.*.
loreStory text shown on the board. Comes from game.content.quests.boards.b<id>.lore.
Objective fieldWhat it does
typecatch (fish hooked and landed), sell (fish sold), dig (successful dig), dive (cache searched or diving contract crate collected).
targetAmount needed.
itemOptional. Fish or item name, or a list. For dive it is the cache id, or contract_<template> for a diving contract crate.
rarityOptional. Rarity or a list.
spotOptional. Spot id or a list.
hoursOptional. { from = 0, to = 5 } in server time; wraps over midnight.
Reward fieldWhat it does
xpXP given when the quest completes.
moneyCash given when the quest completes.
itemsList of { name, count } given when the quest completes.

Other resources can add progress too — see Exports and events.

config.tournaments.lua

KeyWhat it does
EnabledTurns tournaments on.
MaxVisibleActive tournaments shown at once.
LeaderboardLimitRows in the leaderboard.
RequireSingleActiveParticipationA player can be in one running tournament at a time.
EntryMoneyTypecash or bank for the entry fee.
AutoRepeating tournaments, see below.
ListFixed tournaments with dates.

A fixed tournament scores points per species with fishPoints, between startsAt and endsAt (YYYY-MM-DD HH:MM:SS, server time).

Auto creates a new tournament every IntervalHours, lasting DurationHours, from Template. ScoringMode is weight_max (heaviest single fish, in grams) or weight_sum (total weight).

Prizes

Prizes are paid automatically when a tournament ends:

prize = {
    name = 'Biggest Fish Trophy',
    image = 'items/big_catch.png',
    rewards = {
        { rank = 1, money = 2500, xp = 300, items = { { name = 'legendary_bait', count = 5 } } },
        { rankFrom = 2, rankTo = 3, money = 1000 },
    },
},

Only participants with more than 0 points are ranked. Online winners get the reward immediately; offline winners get it a few seconds after they next join. Each tournament is settled once — the result is stored in the database and survives restarts.

config.test.lua

The fishing licence exam is taken at the test ped.

KeyWhat it does
EnabledTurns the exam on.
RequireLicenseToFishThe server refuses to start fishing anywhere without a licence. Use requireLicense on a spot to lock only that spot.
PassPercentScore needed to pass.
MaxAttempts / CooldownSecondsFailed attempts before a cooldown, and its length.
TimeLimitSeconds to finish. Enforced by the server.
LessonsLessons on the Study screen: protected, conduct, control, gear, boats, safety. Texts come from game.test.lessons.<id>.*; remove an id to hide that lesson.
IntroStoryText shown before the exam.
QuestionsQuestions with answers; mark correct ones with correct = true, set multi = true for multiple choice.

The intro, questions and answers are translated from game.test.content.*; the config texts are the fallback. A text edited in the admin panel is shown as written. Correct answers never leave the server.

config.boatrent.lua

shared/config.boatrent.lua
Config.Rent = {
    SpotClearRadius = 7.0,
    AnchorKey = 'G',
    Boats = {
        {
            model = 'dinghy',
            label = 'Dinghy',
            deposit = 500,
            minLevel = 1,
            parkingSpots = {
                vector4(-1793.6165, -1229.7045, -0.4824, 230.8976),
                vector4(-3438.0, 946.0, 0.0, 326.5),
            },
        },
    },
}

A boat spawns at the free parking spot nearest to the renting player, so one list can cover several marinas (Del Perro and Chumash Pier by default). SpotClearRadius is the free space a parking spot needs. The deposit is taken in cash and refunded when the boat is brought back within 20 m of the spot it was rented from. minLevel is checked on the server. AnchorKey is the default key of kf_anchor, which drops and raises the anchor of the boat you are on; the anchor is also in the ox_target menu.

config.diving.lua

Caches

KeyWhat it does
EnabledTurns diving on.
CollectDurationMsSearch time for a cache.
RespawnTimeMsDefault respawn time; each prop can set respawnTimeMs.
CollectDistanceMaximum distance checked by the server.
RequireLicenseSearching a cache requires a fishing licence.
OutlineDistance, OutlineColorOutline on nearby caches.
Targetox_target Icon and Label of the search option. The label is translated from game.content.diving.target.
PropsCaches: id, model, coords (vector4).
OnCollectedServer function that gives the loot. Edit the possibleRewards table inside it.

Scuba gear

Gear is bought and refilled at the diving ped (Marek), paid in cash.

KeyWhat it does
Gear.StarterFreeThe first-dive tutorial gives level-1 gear for free.
Gear.RefillPricePerMinutePrice of a tank refill per minute of missing air.
Gear.Tank.levelscapacity in seconds of air and price per level.
Gear.Fins.levelsswim speed multiplier (max 1.49) and price.
Gear.Light.levelsHead lamp range in metres (0 = none) and price.
Gear.Scanner.levelsCrate marker range, reveal (show the loot tier before opening) and price.
Tutorial.RewardXpXP for finishing the first-dive tutorial, once.
Tutorial.MinSecondsThe server rejects a tutorial finished faster than this.

Diving contracts

Contracts = {
    OffersCount = 3,
    RefreshMinutes = 30,
    MaxActive = 1,
    Areas = {
        { id = 'del_perro_wreck', center = vector3(-2885.0, -270.0, -20.0), radius = 70.0, minTier = 1 },
    },
    Templates = {
        { id = 'salvage', count = { 3, 5 }, tier = 1, reward = { money = { 600, 1100 }, xp = { 60, 110 } } },
    },
},
KeyWhat it does
OffersCountContracts offered at once.
RefreshMinutesOffers regenerate per player after this many minutes.
MaxActiveActive contracts at a time.
AreasReefs and wrecks: id, center, radius, minTier (lowest contract tier sent there).
Templatesid (salvage, recovery, treasure by default), count range of crates, tier, and reward with money and xp ranges and items (name, count range, optional chance in %).

A tier N contract needs tank and scanner level N or higher. Crate positions are generated per contract inside the area.

config.digging.lua

Digging

KeyWhat it does
EnabledTurns digging on.
ShovelItem / RequireShovelItem that starts digging, and whether it is required.
ProgressDurationMsDig time. The server rejects finishes that come too early.
CooldownMsPause between digs.
MaxMoveDistanceHow far the player may move while digging.
MaxGroundDeltaHow far above the ground the player may stand to dig.
DropsWeighted loot: item, min, max, chance. Includes the treasures rusty_key, fossil_shell, amber_chunk and pirate_doubloon.
EnableTestCommand / TestCommandBypassShovelEnables /dig; the shovel bypass also needs Config.Debug = true.
Animation, PropModel, PropBone, PropOffset, PropRotationAnimation and the shovel in hand.

Tutorial and bike

KeyWhat it does
Intro.EnabledThe first talk with the digging ped (Stefan) offers a short tutorial.
Intro.GiveShovelOne shovel when the tutorial starts, once per character.
Intro.RewardXpXP when the tutorial is finished, once.
Intro.BeachRadiusThe "go to the beach" step completes inside this radius of the ped's info.waypoint.
Bike.EnabledThe digging ped lends a bike at any time.
Bike.Model / Bike.PlateBike model (scorcher by default) and plate text.
Bike.SpawnWhere the bike appears at the ped's first zone. Other zones use a point next to the ped; any zone can set its own bikeSpawn.
Bike.DespawnMinutesThe bike is removed after this long with nobody on it, when the player is not near it.

Digging gear and contracts

KeyWhat it does
Gear.Shovel.levelsspeed multiplies ProgressDurationMs, loot is a % bonus for rarer Drops, price.
Gear.Detector.levelsrange for buried caches (0 = none), price.
Gear.Bag.levelscooldown multiplies CooldownMs, price.
Contracts.OffersCount, RefreshMinutes, MaxActiveSame as for diving.
Contracts.Blipsprite, color, alpha and scale of the active contract area on the map.
Contracts.AreasBeaches: id, center, radius, minTier.
Contracts.Templatesid (bait_run, relic, pirate by default), count, tier, reward with money, xp and items (chance is rolled when the offer is made).

Tier 1 contracts need no gear, tier 2 needs detector level 2, tier 3 needs detector and shovel level 3. Upgrades are paid in cash at the digging ped.

config.poaching.lua

shared/config.poaching.lua
Config.Poaching = {
    Enabled = true,
    PoliceJobs = { 'police', 'sheriff' },
    MinPoliceGrade = 0,
    RequireOnDuty = false,
    EvidenceMinutes = 30,
    InspectDistance = 4.0,
    TargetCooldownSeconds = 60,
    Billing = 'money',
    Society = 'society_police',
    ConfiscateProtectedFish = true,
    Alert = { Enabled = true, Chance = 35, CooldownSeconds = 120, BlipSeconds = 90 },
    Offences = {
        { id = 'protected_zone', amount = 2500 },
        { id = 'protected_species', amount = 800, perUnit = true },
        { id = 'no_license', amount = 1000 },
        { id = 'electric_fishing', amount = 5000 },
        { id = 'littering', amount = 300 },
    },
    MaxFine = 25000,
}
KeyWhat it does
EnabledTurns evidence, alerts and fines on.
PoliceJobs, MinPoliceGrade, RequireOnDutyWho gets the "Inspect catch" ox_target option on players and the alerts.
EvidenceMinutesHow long a catch in a protected spot or an electric-fishing catch counts as evidence.
InspectDistanceMaximum distance between officer and angler.
TargetCooldownSecondsSeconds before the same angler can be fined again.
BillingHow the fine is paid, see below.
SocietySociety account that receives the money (money and esx_billing).
ConfiscateProtectedFishFining for protected species removes those fish from the angler.
AlertPolice alert when someone catches a fish in a protected spot: Chance in % per catch, CooldownSeconds per angler, BlipSeconds on the officers' map.
OffencesOffences the officer can pick: id, amount, perUnit (multiplied by the number of protected fish found). Labels come from game.poaching.offences.<id>.
MaxFineUpper limit for a single fine.
BillingBehaviour
moneyTaken from the angler (bank first, then cash) and paid into Society through esx_addonaccount when it is started.
esx_billingA bill is inserted into the billing table for Society.
okokBillingNothing is charged; create the invoice from the koja-fishing:server:fineIssued event.
customNothing is charged; only koja-fishing:server:fineIssued fires.

Protected spots use protected = true in config.spots.lua, protected species protected = true in config.fish.lua. See Exports and events for the poaching events.

config.party.lua

shared/config.party.lua
Config.Party = {
    Enabled = true,
    MaxMembers = 4,
    InviteDistance = 30.0,
    InviteTimeoutSeconds = 60,
    MembersCanInvite = false,
    OpenCommand = 'kf_party',
    OpenKey = 'F7',
    AcceptKey = 'Y',
    DeclineKey = 'N',
    ShareRadius = 150.0,
    ShareModeDefault = false,
    XpBonusPercent = 10,
}
KeyWhat it does
EnabledTurns parties on.
MaxMembersParty size, leader included.
InviteDistanceNearby players shown in the invite list and the maximum distance to invite.
InviteTimeoutSecondsHow long an invite stays open.
MembersCanInvitefalse: only the leader invites. true: every member can.
OpenCommand / OpenKeyCommand and default key of the party window.
AcceptKey / DeclineKeyDefault keys to answer an invite.
ShareRadiusMembers within this distance share a sale and count as fishing together.
ShareModeDefaultWhether the shared wallet starts on. The leader can toggle it.
XpBonusPercentBonus XP for released fish when another member is within ShareRadius.
GoalsGroup goals offered to the leader, see below.
Goals keyWhat it does
OffersCountGoals offered at once.
RefreshMinutesOffers regenerate after this many minutes.
DurationMinutesTime to finish a picked goal.
Templatesid, type, count range, reward with money and xp ranges, optional rarity for catch (that rarity or better).

Goal types: catch (fish landed), sell_value (total $ of fish sold), dive (caches and contract crates), dig_cache (contract caches dug up).

Translations

The locale is loaded on the server too (shared/i18n.lua), so content in the configs is translated at start:

Locale keyTranslates
game.content.items.<key>.*, game.content.fish.<key>.*Item and fish name and description.
game.content.spots.<id>.*Spot name, description and blip label.
game.content.quests.boards.b<id>.*, game.content.quests.q<id>.*Board name, description, lore; quest title and objective label.
game.content.tournaments.*Tournament names, descriptions and prize names.
game.content.hermits.<key>.*Hermit role, story, quest and unlock texts.
game.test.content.*, game.test.lessons.<id>.*Exam intro, questions, answers and lessons.
game.peds.<pedtype>Ped role labels and blips.

The config text is used when a key is missing. The admin panel labels and section descriptions come from the locales as well.

data/skills.json

The skill tree has three branches — wedkarz (angler), klusownik (poacher), handlarz (trader) — listed in meta.trees with the level that unlocks them. Each node has requirements.skills, requirements.level, effect_per_level and an upgrades list whose price is the skill point cost of each level.

Skill idEffect per level
wedkarz_fast_bite% shorter bite wait
wedkarz_luckluck bonus
wedkarz_xp% more XP for released fish
wedkarz_rod_care% lower rod break chance
klusownik_battery_yieldextra fish per battery cycle
klusownik_battery_catch% better grab chance
klusownik_diving_speed% faster cache search
handlarz_sell_bonus, handlarz_negotiator% more money for fish

Keep the ids — the code reads them. The UI shows the catalog the server sends from data/skills.json; web/src/data/skills.json is only a fallback bundled into the UI.