Page cover

user-bounty-hunterBounty Hunter

codex_bounty_hunter adds interactive bounty boards + hunt missions + an optional Bounty Hunter License (ID) flow for RedM.

This documentation is written for server owners and developers. Because the main logic is protected by CFX escrow, you only edit what is intentionally exposed (the Configs/*.lua files and the optional Configs/FunctionsConfig.lua hooks).

What players can do

  • Walk up to a bounty board (Valentine / Blackwater / Saint Denis / Rhodes / Strawberry by default)

  • Open the Bounty Board UI

  • Accept a bounty (a configurable deposit is taken)

  • Follow a clue phase, then a hunt phase

  • Deliver the target alive or dead (some bounties can require alive)

  • Get paid on success

  • Officers can issue a Bounty Hunter License (ID), which can be required to open the board

What you (server owner) can configure

  • Board locations / objects

  • Spawn pools and clue locations per board

  • Mission templates (NPC models, guard count, weapons, rewards multipliers)

  • Framework type (VORP / RSG / TPZ)

  • Deposit percentage and money type

  • Time limit per mission

  • Law job list & grade needed to issue IDs

  • Enable/disable license requirement to open the board

  • Optional integration hooks (money handling, open/close UI hooks, etc.)

Use the sidebar pages to configure, install and customize.


How it works

This section explains the runtime flow in a way that matches what the resource actually does.

1) Board objects exist in the world

The script spawns (or reuses if already present) bounty board objects at the coordinates defined in Configs/ObjectsConfig.lua.

Each object entry binds a board name (example: Valentine) to a set of world coordinates.

2) Players open the board UI

When a player is close enough to a configured board object, they get a Codex Prompt (hold key) to open the board.

When opened:

  1. The client sets NUI focus and shows the UI

  2. The client notifies the server the UI is open for that board

  3. The client requests the list of bounties for that board via a server callback

  4. The UI renders the list and allows Accept / Track / Clear

License gate (optional)

If CodexConfig.EnableCheckBountyIDs = true, the client calls a server callback first to verify the player has a valid issued Bounty Hunter ID (issued by an allowed law job). If the player has no valid license, the board will not open.

3) Accepting a bounty → creates a live bounty row

When a player presses Accept in the UI:

  • The server reads the selected bounty template row (from codex_bounty_templates)

  • A deposit is charged: deposit = floor(reward * CodexConfig.PercentageMoney)

  • A new active bounty row is inserted into codex_bounties

  • A mission payload is built from your spawn pool configs (Configs/BountySpawns.lua) and mission templates (Configs/MissionsConfig.lua)

  • The server starts the mission for that player by sending the payload to the client

Important: Only one active mission per player is allowed at a time.

4) Mission phases

Phase A — Clues

The mission starts in a clue collection phase:

  • The client places blips for each clue location

  • A clue object is spawned (prop model is configurable)

  • The player must collect requiredClues clues (from your spawn entry)

Phase B — Hunt

Once enough clues are collected:

  • The target NPC and guards are spawned at the configured spawn point

  • The target gets a blip

  • Guards and target attack the player

Some mission templates can allow the target to attempt escape (and in the “Drug Baron” template the target can spawn a horse and flee).

Phase C — Deliver

When the target is detected as either:

  • Dead (killed), or

  • Captured alive (hogtied / cuffed — best-effort detection)

…the player must go to the drop-off location for that board.

When they enter the drop-off radius, the client reports completion to the server and cleanup runs.

5) Time limit and failure

A mission time limit is enforced server-side using CodexConfig.MissionTimeLimitSeconds:

  • If the timer expires, the server fails the mission (time_expired)

  • If the player dies during an active mission, the client reports failure (player_died)

When a mission fails, the bounty row is marked inactive so it disappears from boards.

6) Payout

On completion:

  • If requiresAlive = true and the target is delivered dead → the mission fails (target_killed) and pays nothing.

  • Otherwise, payout is:

finalReward = floor(rewardBase * multiplier)

Where multiplier comes from the mission template:

  • rewardAliveMult when delivered alive

  • rewardDeadMult when delivered dead

Money is paid using the default Codex Core account functions, unless you enable hooks and override the money functions.


Installation

Dependencies

The resource declares these dependencies:

  • codex_core

  • oxmysql

  • ox_lib (initialized via @ox_lib/init.lua)

Make sure all three are started before codex_bounty_hunter.

Basic install steps

  1. Put the resource folder in your server resources (example: resources/[codex]/codex_bounty_hunter)

  2. Ensure dependencies start first:

    • ensure oxmysql

    • ensure ox_lib

    • ensure codex_core

  3. Start this resource:

    • ensure codex_bounty_hunter

  4. Import the SQL (see the Database page)

  5. Configure board positions and mission settings in Configs/*.lua

Common “first run” checklist

  • Verify oxmysql connection string is correct

  • Verify codex_core is working and exports are available

  • Confirm your framework setting matches your server:

    • CodexConfig.Framework = 'vorp' | 'rsg' | 'tpz'

  • Confirm you have at least one bounty template row in codex_bounty_templates for each board you want active


Configuration

All user-editable settings for escrow-protected servers are in Configs/*.lua.

Configs/config-main.lua (CodexConfig)

Core

  • DeveloperMode Debug printing. Do not enable on live servers.

  • Framework 'vorp', 'rsg', or 'tpz'

  • EnableCodexPrompts Enables the “hold key” prompts for opening boards and collecting clues.

  • UseHooks When true, the resource will call functions you place in Configs/FunctionsConfig.lua.

Bounties & missions

  • EnableCheckBountyIDs When true, players must have a valid issued Bounty Hunter license (ID) to open bounty boards.

  • MaxBountiesPerPlayer Maximum bounties a player can have (the resource also enforces one active mission at a time).

  • PercentageMoney Deposit ratio required to accept a bounty. Example: 0.5 means a bounty with reward $1000 requires $500 deposit.

  • MoneyType Account type used by CodexCore money functions:

    • 0 money

    • 1 gold

    • 2 roll

  • MissionTimeLimitSeconds Server-enforced time limit. Example default is 1800 (30 minutes).

Law / issuing IDs

  • JobGradeAccess Minimum job grade required to issue IDs with /issueid.

  • LawJobsAllowed A list of jobs that count as law enforcement (also used to validate ID issuers).

  • LicenseItem Item name given when a player completes license info (default: bounty_license).

Keys

CodexConfig.Keys contains key hashes. The script uses CodexConfig.Keys["G"] for prompts by default.

If you change a key value, use only valid key hashes for RedM.

Configs/ObjectsConfig.lua (CodexDataObjects)

Defines bounty board object placements:

  • ModelName object model (default mp005_p_mp_bountyboard02x)

  • ModelCoords world position

  • ModelHeading heading

  • DistanceToReact how close the player must be

  • BoundBoardName board label shown/used when opening the UI

The board name is later normalized to a lowercase internal name:

  • Valentine → valentine

  • Blackwater → blackwater

  • Saint Denis → saintdenis

  • Rhodes → rhodes

  • Strawberry → strawberry

Configs/BountySpawns.lua (CodexBountySpawns)

Defines the spawn pool for each board (must match the internal board name used in DB and normalization).

Each entry contains:

  • id unique spawn ID

  • type mission template key (must exist in MissionsConfig.lua templates)

  • spawn coordinates + heading

  • searchRadius used for clue area (payload)

  • requiredClues number of clues needed to progress

  • clues list of clue positions; each clue can include a type (campfire / footprints / witness, etc.) for your own organization.

Configs/MissionsConfig.lua (CodexBountyMissions)

Drop-offs

DropOffs defines the delivery location per board.

Clue prop

CluePropModel defines the prop model used as clue objects.

Templates

Templates define how targets and guards spawn and behave.

Included templates:

  • basic_outlaw

  • gang_leader

  • drug_baron

Each template includes:

  • label

  • targetModel

  • guards and guardModels

  • weapons

  • spawnRadius

  • escape (target can flee)

  • baronEscapeOnHorse (Drug Baron only)

  • escapeHealthPercent (when to flee)

  • reward multipliers:

    • rewardAliveMult

    • rewardDeadMult


Bounty boards & locations

Boards are defined in Configs/ObjectsConfig.lua as world objects.

Default locations included:

  • Valentine

  • Blackwater

  • Saint Denis

  • Strawberry

  • Rhodes

To add or move a board:

  1. Add a new entry to CodexDataObjects

  2. Choose the world coordinates and heading

  3. Set a BoundBoardName (example "Valentine")

  4. Ensure your database has bounty templates for the corresponding internal board name

Board name matching (important)

The system normalizes board names by:

  • lowercasing

  • removing spaces

Then matches known boards like:

  • "Saint Denis"saintdenis

Your codex_bounty_templates.board values must use the internal names (e.g. saintdenis, not Saint Denis).

Your Configs/BountySpawns.lua keys also must use the internal names.


Missions

Mission selection

When a bounty is accepted, the mission payload is built from:

  • The newly created bounty row (codex_bounties)

  • A random spawn entry from Configs/BountySpawns.lua for that board

  • The mission template referenced by the spawn entry (type) in Configs/MissionsConfig.lua

Clues phase

  • Each spawn entry provides a list of clue positions.

  • The player collects clues until requiredClues is reached.

  • Clues show as map blips and spawn clue objects (prop model from CodexBountyMissions.CluePropModel).

Hunt phase

After enough clues:

  • Target ped spawns using the template targetModel

  • Guards spawn using template guardModels and guards count

  • Weapons are randomly selected from template weapons

Escape behavior

If a template has escape = true, the target can flee when:

  • target health percentage drops below escapeHealthPercent, OR

  • most guards are dead (>= 60% dead)

For drug_baron, if baronEscapeOnHorse = true, a horse is spawned and the target mounts and flees.

Delivery

Each board has a drop-off coordinate in CodexBountyMissions.DropOffs.

Delivery is detected when the player comes close enough to the drop-off after the target is:

  • dead, or

  • captured alive (hogtied/cuffed best-effort)

Success payout

Payout uses the reward multipliers from the template:

  • Alive payout: floor(rewardBase * rewardAliveMult)

  • Dead payout: floor(rewardBase * rewardDeadMult)

If the bounty requires alive delivery (requiresAlive = true) and the target is dead, the mission fails with no payout.


Bounty Hunter License (ID)

This resource includes a Bounty Hunter License system.

What it is

  • Law enforcement can issue an ID card to a player.

  • The ID is stored in the database table codex_bounty_ids.

  • The player can fill out extra license information in the UI and receive the configured license item (CodexConfig.LicenseItem).

Require license to open boards

If CodexConfig.EnableCheckBountyIDs = true, players must have a valid ID row:

  • The server checks codex_bounty_ids for the player’s name.

  • The issuer job must match one of the jobs in CodexConfig.LawJobsAllowed.

If the player does not have a valid ID, the board UI will not open and they will be notified.

Issuing IDs (law officers)

Client command:

Rules:

  • Your job must be in CodexConfig.LawJobsAllowed

  • Your job grade must be >= CodexConfig.JobGradeAccess

When issued:

  • The target player is shown an ID overlay (NUI)

  • The server stores (or updates) the ID row in codex_bounty_ids

Completing license info

When the ID overlay is shown for an issued ID (not view-only), the player can fill in:

  • First name, last name

  • Birth year (must be 1700–1899)

  • Town of birth

  • Father’s first and last names

On successful save:

  • the DB row is updated and marked complete

  • the player receives CodexConfig.LicenseItem (default bounty_license)

Showing your license item to another player

The configured license item is registered as usable. When used:

  • The script finds the nearest player

  • It shows the license UI to that nearby player in view-only mode


Hooks & integration

Because escrow hides most core logic, this resource exposes an optional hook file:

Configs/FunctionsConfig.lua

Enable hooks by setting:

Available hook functions

Client hooks

  • CodexFunctions.Client.OnOpenBoard(boardName) Called when a player tries to open the board UI. Return false to block opening; return true or nil to allow.

  • CodexFunctions.Client.OnCloseBoard() Called when the board UI is closed.

Server hooks

  • CodexFunctions.Server.OnAcceptBounty(source, bountyId) Called when a bounty is accepted.

  • CodexFunctions.Server.OnTrackBounty(source, bountyId) Called when a bounty is tracked.

  • CodexFunctions.Server.OnClearBounty(source) Called when a player clears their active bounty.

  • CodexFunctions.Server.OnIssueID(issuerSource, targetPlayerId, targetName) Called when an officer issues an ID.

Money integration hooks

If you do not want to use CodexCore’s money functions, implement:

  • CodexFunctions.Server.TryTakeMoney(source, amount) -> boolean

Optionally you can also implement:

  • CodexFunctions.Server.GiveMoney(source, amount) -> boolean

If a money hook is enabled and returns true, it is considered successful. If it errors or returns false, the resource falls back to its default behavior.

Example: integrating with another money system

Keep hook functions small and safe: the core calls them using protected pcall.


Database

This resource uses oxmysql and expects specific tables.

Tables used

codex_bounty_templates

Templates shown on the board UI. The Accept button reads from this table.

Required columns used by the resource:

  • id (primary key)

  • board (internal board name: valentine, blackwater, saintdenis, rhodes, strawberry, etc.)

  • name

  • reward

  • description

  • location

  • active (1/0)

Optional column (read safely):

  • capture_alive (1/0) If present and set to 1, that bounty requires alive delivery.

codex_bounties

Live bounties created when a player accepts a bounty. The UI “Accepted” state is based on this table.

Columns used:

  • id

  • name

  • reward

  • description

  • location

  • board

  • active

  • accepted_by

  • accepted_at

  • tracked_by

When a mission finishes or fails, the row is set inactive (active = 0).

codex_bounty_ids

Stores issued bounty hunter IDs.

Columns used:

  • id (format: BH-00000)

  • name (player name)

  • issuer_job

  • issued_by_officer (1/0)

  • issued_at (timestamp)

  • bh_info_completed (1/0)

  • License info fields saved on completion:

    • bh_first_name, bh_last_name

    • bh_birth_year, bh_town_birth

    • bh_father_first, bh_father_last

Importing SQL

Use the SQL files provided with the resource package to create these tables.

If your package contains:

  • create_codex_bounties.sql

  • create_codex_bounty_ids.sql

…import them with your preferred MySQL tool (phpMyAdmin, HeidiSQL, etc.) into the same database used by oxmysql.


Commands, events & callbacks

This page lists what a developer/server owner can rely on.

Commands

/issueid <serverId>

Client command for law officers to issue a Bounty Hunter ID to a player.

  • Requires job in CodexConfig.LawJobsAllowed

  • Requires grade >= CodexConfig.JobGradeAccess

/codex_bounty_refresh [board]

Server command to force-refresh open bounty board UIs (admin only).

  • With a board name: refreshes only that board’s open UIs

  • Without args: refreshes all open UIs

Server callbacks (CodexCore)

  • codex_bounty:server:GetBounties(boardName) Returns board bounties from codex_bounty_templates.

  • codex_bounty:server:CheckPlayerBountyIDs() Checks if the player has a valid issued license in codex_bounty_ids.

  • codex_bounty_hunter:CheckCooldown() Queries codex_bounty_ids for the player’s name and returns (true, id) if found, otherwise false.

Server events

  • codex_bounty:server:UIOpened(boardName)

  • codex_bounty:server:UIClosed()

  • codex_bounty:server:AcceptBounty(templateId)

  • codex_bounty:server:TrackBounty(bountyId)

  • codex_bounty:server:ClearBounty()

  • codex_bounty:server:CompleteMission({ bountyId, alive })

  • codex_bounty:server:FailMission({ reason })

  • codex_bounty:server:FailMissionDirect(targetSrc, reason)

  • codex_bounty:server:IssueID(targetPlayerId, targetName)

  • codex_bounty:server:SaveBHInfo(data)

  • codex_bounty:server:RegisterBH(data) (generates an ID payload and shows it)

Client events

  • codex_bounty:client:OpenBountyBoardUI(boardName)

  • codex_bounty:client:PushBounties(bounties, playerServerId)

  • codex_bounty:client:StartMission(payload)

  • codex_bounty:client:MissionFinished({ paid })

  • codex_bounty:client:MissionFailed({ reason })

  • codex_bounty:client:ShowIssuedID(payload)

  • codex_bounty:client:ShowBountyID(payload)

  • codex_bounty:client:UseLicenseNearest

  • codex_bounty:client:Notify(msg, time)


Troubleshooting

The board prompt never appears

Checklist:

  • CodexConfig.EnableCodexPrompts = true

  • Your board object coords in Configs/ObjectsConfig.lua are correct

  • The model name is valid (mp005_p_mp_bountyboard02x by default)

  • You are within DistanceToReact

The board UI opens but is empty

  • Confirm you have rows in codex_bounty_templates where:

    • board matches the internal name (valentine, blackwater, etc.)

    • active = 1

  • Confirm oxmysql is connected and working

  • Use /codex_bounty_refresh to refresh open UIs (admin)

Players cannot open boards (license error)

  • Set CodexConfig.EnableCheckBountyIDs = false to disable license requirements, OR

  • Ensure players have rows in codex_bounty_ids issued by a job in CodexConfig.LawJobsAllowed

Accept button does nothing

  • Ensure oxmysql is running

  • Ensure the bounty template ID exists and is active

  • Check server console for “[Codex Bounty]” logs

Mission fails instantly

Common causes:

  • Another active mission exists for that player (only one active mission per player)

  • The mission payload failed to build because there are no spawn entries for that board in Configs/BountySpawns.lua

Payout doesn’t work

  • If you enabled hooks, ensure your money hooks return true on success

  • Otherwise, ensure codex_core account functions are working and CodexConfig.MoneyType matches your economy setup

Developer debugging tips

  • Enable CodexConfig.DeveloperMode = true temporarily to print helpful logs.

  • Disable it again for production servers.


Last updated

Was this helpful?