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

# Exports

Server side exports, built for a job center, a boss menu or any script that hands out jobs.

`target` is either a **server id** (number, player has to be online) or an **ESX identifier** (string, works offline too).

```lua
exports['l-multijob']:AddMultijob(target, job, grade)
exports['l-multijob']:RemoveMultijob(target, job)
exports['l-multijob']:SetMultijobGrade(target, job, grade)
exports['l-multijob']:GetMultijobs(target)
exports['l-multijob']:GetMultijobsDetailed(target)
exports['l-multijob']:HasMultijob(target, job)
exports['l-multijob']:CanAddMultijob(target, job)
exports['l-multijob']:SetActiveMultijob(target, job)
exports['l-multijob']:GetMultijobHolders(job)
exports['l-multijob']:HasJobClass(target, key)
exports['l-multijob']:GetJobClass(job)
exports['l-multijob']:NotifyJobLeft(target, job)
exports['l-multijob']:GetCategoryLocks(target)
exports['l-multijob']:SetCategoryLock(target, hours, reason)
exports['l-multijob']:ClearCategoryLock(target)
```

### AddMultijob

```lua
local ok, err, message = exports['l-multijob']:AddMultijob(source, 'police', 3)
```

Adds a job to the player's list. Returns `ok`, plus an error key and a finished message when it failed:

| Error              | Meaning                                                                                         |
| ------------------ | ----------------------------------------------------------------------------------------------- |
| `unknown_job`      | The job does not exist in ESX                                                                   |
| `job_blacklisted`  | The job is the standard job and can never be added                                              |
| `max_jobs`         | The player is already at their job limit (`Config.MaxJobs`, or their own limit from the bypass) |
| `category_blocked` | The faction rules refuse it, either a running lock or a conflicting category                    |
| `player_not_found` | No player for that server id or identifier                                                      |

Show `message` to your player, not `err`. The key belongs to l-multijob's locale table, so running it through your own script's locale prints the raw key.

Adding never changes the active job.

### RemoveMultijob

```lua
exports['l-multijob']:RemoveMultijob(source, 'police')
```

Removes a job. Returns `true` or `false`. If the removed job was the active one, the player is switched to the next job they hold, or to the standard job.

### SetMultijobGrade

```lua
exports['l-multijob']:SetMultijobGrade(source, 'police', 4)
```

Changes the grade of a job the player already holds. Returns `true` or `false`. If it is the active job, the live grade is updated too, so promotions apply right away.

### GetMultijobs

```lua
local jobs = exports['l-multijob']:GetMultijobs(source)
-- { police = 3, mechanic = 0 }
```

Returns the job list as a job to grade table.

### GetMultijobsDetailed

```lua
local jobs = exports['l-multijob']:GetMultijobsDetailed(source)
-- { { name = 'police', label = 'Police', grade = 3, gradeLabel = 'Sergeant', salary = 120, active = true }, ... }
```

Returns the same list with the labels, the grade salary and which one is currently active, sorted by label. The standard job is never listed.

### HasMultijob

```lua
if exports['l-multijob']:HasMultijob(source, 'police') then
```

Returns `true` when the player holds that job.

### CanAddMultijob

```lua
local allowed, info = exports['l-multijob']:CanAddMultijob(source, 'police')
if not allowed then
    print(info.reason, info.message)
end
```

The check on its own, without adding anything. Use it to grey out a hire button or to refuse early. Returns `false` when the job is new for that player and their list is already at their job limit, or when the faction rules refuse it. Jobs they already hold, grade changes and the standard job return `true`.

`info` carries `reason` (`max_jobs`, `locked` or `conflict`) and a ready to use `message`.

This is the one used in the es\_extended `/setjob` patch, see Installation.

### SetActiveMultijob

```lua
exports['l-multijob']:SetActiveMultijob(source, 'police')
```

Force switches the active job, ignoring the switch cooldown. The job has to be in the player's list, or be the standard job. Returns `true` or `false`.

### GetMultijobHolders

```lua
local holders = exports['l-multijob']:GetMultijobHolders('police')
-- { { identifier = 'char1:abc...', grade = 3 }, { identifier = 'char1:def...', grade = 0 } }
```

Returns every player who holds that job in their list, online or offline, as a list of identifier and grade. Online players come from memory, offline players from a single database read, deduplicated by identifier. This is a menu open call, not something to run every frame.

Built for a boss menu, so it can list staff who carry the job in their portfolio, not only the players whose active job is the company.

### HasJobClass

```lua
if exports['l-multijob']:HasJobClass(source, 'state') then
```

Returns `true` when the player has any job, active or in their list, that belongs to the given category key. `HasJobClass(source, 'civ')` matches a player who holds any job that is in no category.

Returns `false` when `Config.Categories.enabled` is `false`. See Icons and categories.

### GetJobClass

```lua
local key = exports['l-multijob']:GetJobClass('police')
-- 'state'
```

Takes a job name and returns its category key, or `'civ'` when the job is in no category. Returns `'civ'` when `Config.Categories.enabled` is `false`.

### Faction lock

```lua
exports['l-multijob']:NotifyJobLeft(target, job)
local lock = exports['l-multijob']:GetCategoryLocks(target)
exports['l-multijob']:SetCategoryLock(target, hours, reason)
exports['l-multijob']:ClearCategoryLock(target)
```

| Export              | What it does                                                                                                                  |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `NotifyJobLeft`     | Call it when your own script takes a job away without going through `RemoveMultijob`, so the lock still starts                |
| `GetCategoryLocks`  | The running lock as `{ until_, reason, secondsLeft }`, or `nil`. A `secondsLeft` of `-1` means it runs until someone lifts it |
| `SetCategoryLock`   | Sets a lock by hand. `hours` of `0` or `nil` means until lifted, decimals work. Overwrites a running lock                     |
| `ClearCategoryLock` | Lifts the lock again                                                                                                          |

See Faction lock for what the lock actually does.

### Offline behaviour

Calls with an identifier for an offline player are applied to the database in the background and return `true` right away. When the change affects the active job, the ESX `users` table is updated as well, so the player gets the right job on their next login.

A numeric server id never resolves to an offline player, server ids only exist while someone is connected. Use the identifier for offline work.
