> For the complete documentation index, see [llms.txt](https://aero-labs.gitbook.io/aero-labs-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://aero-labs.gitbook.io/aero-labs-docs/scripts/aboosting.md).

# ABoosting

A character-based vehicle boosting system with a custom tablet, contract market, crews, class progression and a full hack, plate, paint and delivery flow.

![ABoosting](https://3178353394-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fm2Hc1pmEtJtEBI0blIeE%2Fuploads%2FT64hklcpExyvACwYcgTv%2FABoosting.png?alt=media)

ABoosting is a **vehicle boosting system** built around a custom Æro Labs tablet. Players register a display name, buy or claim contracts from a rotating market, bring a crew, then find the car, hack it, swap its plates, respray it and deliver it before the timer runs out.

## Features

* **Custom tablet** with animated navigation, vehicle previews and personal profiles
* **Character-based accounts** with display names, profile pictures, contract history, market history and a leaderboard
* **Contract market** with **S, A, B, C and D** classes, rotating listings, prices, payouts, cooldowns and item requirements
* **Progression**: start on D-class and unlock higher classes by completing boosts
* **Weekly free contracts** with a configurable allowance
* **Crews** of up to six players, with payout shares that you split yourselves
* **Full objective flow**: locate the car, a three-stage OBD hack, front and rear plate swaps, a paint job on high classes, then delivery
* **Equipment market** for OBD readers, plates, screwdrivers and spray cans
* **Admin tab** to create contracts, publish or remove listings, grant contracts and moderate display names
* **Testing switches** to skip the minigames on a development server

## Requirements

| Dependency                                                                            | Required | Notes                                                 |
| ------------------------------------------------------------------------------------- | -------- | ----------------------------------------------------- |
| Qbox, QBCore or ESX                                                                   | Yes      | Detected automatically                                |
| [ox\_lib](https://github.com/overextended/ox_lib)                                     | Yes      |                                                       |
| [oxmysql](https://github.com/overextended/oxmysql)                                    | Yes      | Saves profiles, contracts and the market              |
| [CircuitBreakerMinigame\_lua](https://github.com/BerkieBb/CircuitBreakerMinigame_lua) | Yes      | The OBD hack minigame. Keep this exact resource name. |
| ox\_inventory, qb-inventory or an ESX inventory                                       | Yes      | Detected automatically                                |
| ox\_target or qb-target                                                               | Optional | Otherwise a built-in "press E" prompt is used         |
| OneSync                                                                               | Yes      | Needed for the networked contract cars                |

{% hint style="info" %}
ABoosting doesn't include police dispatch alerts. Hook it up to your own dispatch if you want police to respond.
{% endhint %}

## Installation

{% stepper %}
{% step %}

### Install the dependencies

Install ox\_lib, oxmysql and [**CircuitBreakerMinigame\_lua**](https://github.com/BerkieBb/CircuitBreakerMinigame_lua). Don't rename the Circuit Breaker folder: ABoosting looks for the name `CircuitBreakerMinigame_lua`.
{% endstep %}

{% step %}

### Add the resource

Drag the `ABoosting` folder into your `resources` folder. When updating, **replace the whole folder**. Don't merge old and new files.
{% endstep %}

{% step %}

### Import the database

Import `ABoosting/install/schema.sql` into your server's database using HeidiSQL, phpMyAdmin or your host's database panel.

**ESX only:** also look at `install/esx_items.sql` and `install/addoninventory.sql`, and import the ones your inventory needs.
{% endstep %}

{% step %}

### Add the items

See **Inventory items** below, then copy the five images from `ABoosting/install/item_images/` into your inventory's image folder.
{% endstep %}

{% step %}

### Add it to server.cfg

Start the dependencies **before** ABoosting:

```cfg
ensure oxmysql
ensure ox_lib
# your framework, inventory and (optional) target
ensure CircuitBreakerMinigame_lua
ensure ABoosting
```

{% endstep %}

{% step %}

### Give admins access (optional)

See **Admin access** below.
{% endstep %}
{% endstepper %}

### Inventory items

| Item              | What it's for                                       |
| ----------------- | --------------------------------------------------- |
| `aboostingtablet` | Opens the tablet. It's not used up.                 |
| `aobdreader`      | Needed for the OBD hack                             |
| `anumberplate`    | Replacement number plate, needed for every contract |
| `ascrewdriver`    | Plate tool for A and S contracts                    |
| `aspraycan`       | Paint tool for A and S contracts                    |

{% tabs %}
{% tab title="ox\_inventory" %}
Copy the entries from `ABoosting/install/ox_items.lua` into `ox_inventory/data/items.lua`. The tablet must open through this event:

```lua
['aboostingtablet'] = {
    label = 'Boosting Tablet',
    weight = 900,
    stack = false,
    close = true,
    consume = 0,
    client = { event = 'aboosting:client:useTabletItem' }
},
```

Keep `consume = 0` so the tablet isn't used up. If you already have an `aboostingtablet` entry, replace it rather than adding a second one.
{% endtab %}

{% tab title="qb-inventory (QBCore / Qbox)" %}
Copy the entries from `ABoosting/install/qb_items.lua` into your item list, usually `qb-core/shared/items.lua`.
{% endtab %}

{% tab title="ESX" %}
Import `install/esx_items.sql` and register the items the way your inventory expects.
{% endtab %}
{% endtabs %}

### Admin access

The tablet's **Admin** tab needs the ACE permission `aboosting.admin`. Add this to your `server.cfg`:

```cfg
add_ace group.admin aboosting.admin allow
add_principal identifier.license:YOUR_LICENSE_HERE group.admin
```

If your account is already in `group.admin`, you only need the first line. Having txAdmin access on its own doesn't grant this permission.

Two **server console** commands help with permissions (replace `1` with the player's server ID):

| Command                    | What it does                                           |
| -------------------------- | ------------------------------------------------------ |
| `aboosting_admincheck 1`   | Shows whether that player has admin access             |
| `aboosting_adminrefresh 1` | Refreshes their tablet permissions without a reconnect |

## How a boost works (for players)

### 1. Open the tablet

Use the **Boosting Tablet** item. The first time, register a **display name**. This is the name other players see; your real character name isn't shown. You can also set a profile picture.

### 2. Get a contract

Open **Market** to see the contracts on offer. Each one shows its class, car, price and payout. Buy one, or claim a **weekly free contract** if you have one left (2 per week by default, D-class only, resetting every Monday UTC).

You also need the right equipment, which you can buy in the market:

| Class       | Items needed                                     |
| ----------- | ------------------------------------------------ |
| **D, C, B** | OBD Reader, Number Plate                         |
| **A, S**    | OBD Reader, Number Plate, Screwdriver, Spray Can |

### 3. Bring a crew (optional)

Invite up to five other players by **display name**, for six people including you. Invites last 60 seconds. As leader, you set each member's **payout share**, and the shares must add up to 100%.

### 4. Start the contract

Start the contract from the tablet. You get a waypoint to the car and a **30-minute** timer. Every step below is done at the car: look at it with your target eye (**ABoosting | Work on vehicle**), or press **E** when the prompt appears.

### 5. Hack the car

With an **OBD Reader**, beat **three stages of Circuit Breaker** (beginner, easy, medium). If you fail a stage, try again at the car.

### 6. Swap the plates

The camera zooms in on each plate:

* **Scroll down** to unscrew the old plate, then **scroll up** to screw the new one on. Do the front first, then the rear.
* Each plate has four screws, and each screw takes three scroll ticks.
* Press **Backspace** to stop. You can resume from the car.

### 7. Respray the car (A and S only)

Drive to the marked **spray station**, then pick the colour the contract asks for. Spraying the **wrong colour cuts the payout by 18%**.

### 8. Deliver

Drive to the drop-off point and confirm the delivery at the car. Everyone in the crew is paid their share, and you earn **XP** towards your level.

### Progression

Everyone starts on **D-class**. Complete contracts to unlock the next class. By default:

| To unlock | Complete             |
| --------- | -------------------- |
| C-class   | 10 D-class contracts |
| B-class   | 15 C-class contracts |
| A-class   | 20 B-class contracts |
| S-class   | 25 A-class contracts |

XP also gives you a **level**: Rookie, Courier, Operator, Specialist, Professional and Legend. Check your progress in the **Levels** tab and compare yourself with others on the **leaderboard**.

## Admin tools

Players with `aboosting.admin` get an **Admin** tab on the tablet where they can:

* create custom contracts,
* publish and remove market listings,
* grant contracts to players, and
* moderate display names.

Admin-created prices and rewards are capped by `Config.Admin` (see Configuration).

## Configuration

The settings are split into files in `ABoosting/config/`. Keep the root `config.lua` file. It loads the others.

| File            | Controls                                                                       |
| --------------- | ------------------------------------------------------------------------------ |
| `framework.lua` | Framework, inventory, target system, tablet item and tablet command            |
| `gameplay.lua`  | Timer, crew size, progression, weekly contracts, minigames, levels and testing |
| `market.lua`    | Equipment shop, payment accounts, class rules, contracts and market rotation   |
| `locations.lua` | Car spawn points, spray stations, drop-offs and paint colours                  |
| `vehicles.lua`  | Plate minigame, spray animation, markers and car spawning                      |
| `interface.lua` | Vehicle images, inventory images, notifications, HUD position and leaderboard  |
| `admin.lua`     | Admin permission and limits                                                    |

### framework.lua

```lua
Config.Framework = 'auto'
Config.Inventory = 'auto'
Config.Target = 'auto'   -- 'auto', 'ox_target', 'qb-target', 'textui'

Config.TabletItem = 'aboostingtablet'
Config.RequireTabletItem = true

Config.EnableTabletCommand = false
Config.TabletCommand = 'aboosting'
Config.TabletKey = 'F7'

Config.TabletWorldAnimation = true
Config.BlackMoneyItem = 'black_money'
Config.CustomGiveVehicleKeys = nil
```

| Option                               | Description                                                                                                                                       |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Framework` / `Inventory` / `Target` | Leave on `'auto'` to detect them. Use `'textui'` for the built-in "press E" prompt instead of a target eye.                                       |
| `TabletItem`                         | The item that opens the tablet.                                                                                                                   |
| `EnableTabletCommand`                | Set to `true` to also open the tablet with `/aboosting` or **F7**. The player still needs the item while `RequireTabletItem` is `true`.           |
| `TabletWorldAnimation`               | Shows the player holding a tablet while it's open.                                                                                                |
| `BlackMoneyItem`                     | The item used for `black_money` payouts on Qbox and QBCore.                                                                                       |
| `CustomGiveVehicleKeys`              | Car keys are given automatically with `qbx_vehiclekeys` or `qb-vehiclekeys`. For any other key script, set this to your own function (see below). |

Example for another key script:

```lua
Config.CustomGiveVehicleKeys = function(source, vehicle, plate)
    exports['my-keys']:GiveKeys(source, plate) -- example only: use your key script's export
end
```

### gameplay.lua

```lua
Config.MaxPartyMembers = 6
Config.InviteLifetime = 60
Config.ContractSeconds = 30 * 60

Config.WeeklyFreeContracts = 2
Config.WeeklyFreeAllowedClasses = { D = true }

Config.ClassProgression = {
    Order = { 'D', 'C', 'B', 'A', 'S' },
    BaseRequired = 10,
    StepIncrease = 5
}

Config.WrongPaintPenalty = 0.18
Config.RequiredDistanceFromLeader = false
```

| Option                       | Description                                                                                                                      |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `MaxPartyMembers`            | Largest crew size, including the leader.                                                                                         |
| `InviteLifetime`             | Seconds before a crew invite expires.                                                                                            |
| `ContractSeconds`            | Time limit for a contract (`30 * 60` = 30 minutes).                                                                              |
| `WeeklyFreeContracts`        | Free contracts per player per week.                                                                                              |
| `WeeklyFreeAllowedClasses`   | Classes that can be claimed for free, such as `{ D = true, C = true }`.                                                          |
| `ClassProgression`           | Class order, completions needed for the first unlock (`BaseRequired`), and how many more each next class needs (`StepIncrease`). |
| `WrongPaintPenalty`          | Payout cut for the wrong paint colour (`0.18` = 18%).                                                                            |
| `RequiredDistanceFromLeader` | If `true`, crew members must be within 80 m of the leader to start.                                                              |
| `Config.Levels`              | Level names and the XP each one needs.                                                                                           |

**Circuit Breaker difficulty:** each of the three stages has a `map` (1–6) and a `difficulty` (0 = beginner to 3 = hardest). There must always be exactly three stages:

```lua
Config.CircuitBreaker = {
    Resource = 'CircuitBreakerMinigame_lua',
    Stages = {
        { map = 1, difficulty = 0 },
        { map = 2, difficulty = 1 },
        { map = 3, difficulty = 2 }
    }
}
```

**Testing switches:**

```lua
Config.Testing = {
    SkipMinigames = false,
    SkipCircuitBreaker = false,
    SkipPlateScrews = false
}
```

{% hint style="warning" %}
The testing switches are for development servers only. **Keep them all `false` on a live server**, or players can skip the hack and plate minigames.
{% endhint %}

### market.lua

**Equipment shop:** each item has a price and a short description:

```lua
Config.MarketItems = {
    { name = 'ascrewdriver', label = 'Screwdriver', price = 750, amount = 1, description = '...', image = 'ascrewdriver.png' },
    { name = 'aspraycan',    label = 'Spray Can',   price = 1100, amount = 1, description = '...', image = 'aspraycan.png' },
    { name = 'anumberplate', label = 'Number Plate', price = 400, amount = 1, description = '...', image = 'anumberplate.png' },
    { name = 'aobdreader',   label = 'OBD Reader',  price = 1800, amount = 1, description = '...', image = 'aobdreader.png' }
}
```

**Money:**

```lua
Config.PaymentAccount = 'bank' -- where payouts go: 'cash', 'bank' or 'black_money'
Config.PriceAccount = 'bank'   -- what contract purchases are paid from
```

**Classes:** cooldown (seconds), XP per completion, payout multiplier, required items, and whether a paint job is needed:

```lua
Config.Classes = {
    S = { cooldown = 1200, xp = 220, multiplier = 1.0, required = { 'ascrewdriver', 'aspraycan', 'anumberplate', 'aobdreader' }, optional = {}, paint = true },
    D = { cooldown = 300,  xp = 35,  multiplier = 1.0, required = { 'anumberplate', 'aobdreader' }, optional = {}, paint = false },
    -- A, B and C work the same way
}
```

**Contracts:** add or remove cars. `model` is the spawn name, `reward` is the payout and `price` is the cost to buy the contract:

```lua
Config.Offers = {
    { id = 's_italirsx', class = 'S', model = 'italirsx', name = 'Grotti Itali RSX', reward = 48000, price = 9200, image = '' },
    { id = 'd_asea',     class = 'D', model = 'asea',     name = 'Declasse Asea',    reward = 4700,  price = 650,  image = '' },
}
```

Each `id` must be unique. Leave `image` empty to use the car picture from the FiveM docs, or set your own image URL for add-on cars.

**Market rotation:**

```lua
Config.MarketRotation = {
    Enabled = true,
    IntervalSeconds = 20 * 60,
    ListingSeconds = 20 * 60,
    VisibleCount = 6,
    AlwaysIncludeD = true
}
```

| Option            | Description                                                                        |
| ----------------- | ---------------------------------------------------------------------------------- |
| `IntervalSeconds` | How often the market refreshes.                                                    |
| `ListingSeconds`  | How long each listing stays up. Contracts players have already bought stay theirs. |
| `VisibleCount`    | How many contracts are on offer at once.                                           |
| `AlwaysIncludeD`  | Always show at least one D-class contract, so new players can start.               |

### locations.lua

* `Config.Spawns`: where contract cars spawn (`vector4` with heading).
* `Config.SprayStations`: where A and S cars are resprayed.
* `Config.Dropoffs`: delivery points.
* `Config.PaintColours`: the colours players can choose from. `colour` is the GTA paint ID and `hex` is the colour shown in the menu.

Keep spawn points in open spaces. ABoosting won't spawn a car where the spot is already occupied.

### vehicles.lua

| Option                            | Description                                                                      |
| --------------------------------- | -------------------------------------------------------------------------------- |
| `Config.Plate.ScrollsPerScrew`    | Scroll ticks needed per screw.                                                   |
| `Config.Plate.MaxDurationSeconds` | Time limit for the whole plate swap.                                             |
| `Config.Plate.ModelOffsets`       | Per-car corrections if the screws don't line up with the plate on an add-on car. |
| `Config.SprayDurationMs`          | How long spraying takes.                                                         |
| `Config.ShowWorldMarkers`         | Shows markers at the spray station and drop-off.                                 |
| `Config.DebugVehicleSpawns`       | Prints car-spawn details to the console. Set to `false` on a live server.        |

### interface.lua

| Option                           | Description                                                                                   |
| -------------------------------- | --------------------------------------------------------------------------------------------- |
| `Config.Notifications`           | `'builtin'` (tablet style), `'ox_lib'`, `'qbcore'` or `'esx'`.                                |
| `Config.DefaultHudPosition`      | Where the contract HUD sits: `right-center`, `right-bottom`, `left-center` or `left-bottom`.  |
| `Config.InventoryImageDirectory` | `'auto'` uses your inventory's image folder for item pictures.                                |
| `Config.AvatarAllowedHosts`      | Limit profile picture links to these websites, such as `{ 'i.imgur.com' }`. Empty allows any. |
| `Config.LeaderboardLimit`        | How many players the leaderboard shows.                                                       |

### admin.lua

```lua
Config.Admin = {
    Enabled = true,
    AcePermission = 'aboosting.admin',
    DefaultListingSeconds = 1800,
    MaxListingSeconds = 86400,
    MaxCreatePrice = 1000000,
    MaxCreateReward = 5000000
}
```

`MaxCreatePrice` and `MaxCreateReward` stop admins from creating contracts that are too expensive or pay out too much.

## Troubleshooting

<details>

<summary>The tablet doesn't open</summary>

Check that the `aboostingtablet` item exists only once in your inventory, that you have one, and (ox\_inventory) that it uses `client = { event = 'aboosting:client:useTabletItem' }`. Look in F8 and the server console for errors.

</details>

<details>

<summary>"GTA Circuit Breaker is missing"</summary>

Install [CircuitBreakerMinigame\_lua](https://github.com/BerkieBb/CircuitBreakerMinigame_lua) with exactly that folder name, and `ensure` it **before** ABoosting.

</details>

<details>

<summary>Database error or missing column</summary>

Import the latest `install/schema.sql` into the database your server uses. Back up first.

</details>

<details>

<summary>The Admin tab is missing</summary>

Run `aboosting_admincheck <id>` in the server console, check your `add_ace` / `add_principal` lines, and reconnect.

</details>

<details>

<summary>The contract car doesn't spawn</summary>

Make sure OneSync is on, the car's spawn name in `Config.Offers` is correct, and the spawn point is clear of other vehicles.

</details>

<details>

<summary>The market is empty</summary>

Check `Config.MarketRotation` is enabled and that `schema.sql` was imported. Look in the server console for SQL errors.

</details>

<details>

<summary>Items have no pictures</summary>

Copy the five PNGs from `install/item_images/` into your inventory's image folder, and check `Config.InventoryImageDirectories` in `interface.lua`.

</details>
