# Society

**codex\_society** is a fully configurable **job & society management system** for **RedM (VORP Core)**.

It is designed so that **customers only need access to the configuration file and public exports**. All core logic is **CFX escrowed** and never needs to be edited.

***

**Key Features ✨**

* 🏦 **Society / Job Accounts** Shared job money stored in the database (deposits & withdrawals).
* 👥 **Employee Management** Hire, fire, promote, demote, and manage access to the job account.
* 🕒 **Duty System** On/Off-duty with **blip color changes** for visibility.
* 📦 **Job Stash** Shared inventory per job using `vorp_inventory`.
* 👚 **Wardrobe Integration** Configurable function to hook into any clothing/wardrobe script.
* 💵 **Salary System** Per job and per grade salaries, paid every X minutes.
* 💬 **Job Chat** Optional job-only chat channels.

***

#### Requirements 🧩 <a href="#requirements" id="requirements"></a>

**Framework / Core**

* **VORP Core**

**Dependencies**

Make sure these start **before** `codex_society`:

* `oxmysql` – database handler
* `vorp_inventory` – shared inventories/stashes
* `codex_core`
* `mega_nplayerselector` – used for hiring menus
* `fx-input` – input menus for UI

**Example server.cfg order:**

```lua
ensure oxmysql
ensure vorp_core
ensure codex_core
ensure mega_nplayerselector
ensure fx-input
ensure codex_society
```

#### Files Included 📁 <a href="#files-included" id="files-included"></a>

* `fxmanifest.lua` – resource metadata (do not modify unless you know what you’re doing)
* `config.lua` ✅ – **main configuration file** (this is what your customers edit)
* `docs.lua` ✅ – examples of how to use exports/events in other scripts
* `insert.sql` ✅ – required database structure
* `client.lua` / `server.lua` (encrypted) – main logic (not editable by customers)

> 🛡️ **Important:** Customers should only touch:
>
> * `config.lua`
> * Their own scripts that **call** the public exports/events.

***

#### Database Setup 🗄️ <a href="#database-setup" id="database-setup"></a>

1. Open your database manager (Heidisql, etc.).
2. Import the provided **`insert.sql`** file.
3. This will create the table used by `codex_society` to store **society account balances**.

> ⚠️ Do **not** modify the table structure unless you know exactly what you’re doing. The script relies on the schema created by `insert.sql`.

***

#### How Players Use It In-Game 🎮 <a href="#how-players-use-it-in-game" id="how-players-use-it-in-game"></a>

Once configured:

* Players with a configured job go to the **job location** you set in `config.lua`.
* They see a 3D text prompt (e.g. `[G] - Job Menu`).
* Press the configured key (by default **G**) to open:
  * Society account / ledger
  * Employee management (boss only)
  * Job stash
  * Wardrobe (via your wardrobe system)
* Use commands like `/onduty`, `/offduty`, `/job` (names configurable) for:
  * Duty status
  * Job chat

***

#### Page 2 — Configuration ⚙️ <a href="#page-2-configuration" id="page-2-configuration"></a>

```
# Configuration ⚙️

--All behavior is controlled via **`config.lua`**.  
--Customers **never** need to open or edit server/client code.

## Basic Settings 🌍


Config = {}

Config.Language = 'en'
Config.UnemployedJob = {
    Job = 'unemployed',
    Grade = 0
}
```

#### Commands 💬 <a href="#commands" id="commands"></a>

```
Config.Commands = {
    OnDuty = 'onduty',
    OffDuty = 'offduty',
    Chat = 'job'
}
```

* `/onduty` – puts player **on duty**, updates blip color.
* `/offduty` – puts player **off duty**.
* `/job` – sends a message in **job-only chat** (if enabled for that job).

You can rename these, e.g.:

```lua
Config.Commands = {
    OnDuty = 'duty_on',
    OffDuty = 'duty_off',
    Chat = 'company'
}
```

> 📝 Don’t forget to update your server rules / help commands if you rename them.

***

#### Menu Interaction 🎛️ <a href="#menu-interaction" id="menu-interaction"></a>

```
Config.MenuOpen = 0x760A9C6F -- G
Config.Text = '[G] - Job Menu'
Config.MenuDistance = 1.5
```

* **MenuOpen** – control hash for the key that opens the job menu (default **G**).
* **Text** – 3D text prompt shown near the job menu location.
* **MenuDistance** – max distance from the job location where menu can be opened.

***

#### Wardrobe Integration 👚 <a href="#wardrobe-integration" id="wardrobe-integration"></a>

```
Config.WardrobeOpen = function()
    TriggerEvent('kd_clothingstore:openWardrobe', true)
end
```

This function is called when a player selects **Wardrobe** in the job menu.

To use a different wardrobe script, replace the body:

```
Config.WardrobeOpen = function()
    -- Example: your custom wardrobe
    TriggerEvent('your_wardrobe:open', true)
end
```

> 🔗 This is the only place you plug your wardrobe system into codex\_society.

***

#### Salary System 💵 <a href="#salary-system" id="salary-system"></a>

```lua
Config.SalaryMinutes = 30

Config.SalaryJobs = {
    ['doctor'] = {
        [0] = 15,
        [1] = 25,
    },
}
```

* **Config.SalaryMinutes**
  * Interval (in minutes) between salary payouts.
* **Config.SalaryJobs**
  * Key: job name (string)
  * Value: table of `[grade] = amount`

Example:

```lua
Config.SalaryJobs = {
    ['doctor'] = {
        [0] = 15,  -- junior doctor
        [1] = 25,  -- senior doctor
    },
    ['sheriff'] = {
        [0] = 10,
        [1] = 20,
        [2] = 35,
    },
}
```

> Set an amount to `0` if a grade should **not receive salary**.

***

#### Job Configuration 🧭 <a href="#job-configuration" id="job-configuration"></a>

Each job you want managed by codex\_society goes into `Config.Jobs`.

**Example Job**

```lua
Config.Jobs = {
    ['saloonval'] = {
        JobLabel = 'Valentine Saloon',

        Location = vector3(-313.49, 804.9, 118.98),

        Blip = {
            Enabled = true,
            Sprite = 1879260108,
            OffDutyColor = 0x3F90ADF0,
            OnDutyColor  = 0xA2329CFC,
            Name = 'Smithfields Saloon',
        },

        Chat = {
            Enabled = false,
            Label = 'Smithfields Saloon',
        },

        Inventory = {
            Label = 'Smithfields Saloon Stash',
            Capacity = 5000,
        },

        BossRank = 1,
        InventoryOpen = 0,
        JobMinimumGrade = 0,
        Webhook = '',
    },
}
```

**Field Breakdown 🧾**

* **Key** (`'saloonval'`)
  * Must match the **job name** used by your framework.
* **JobLabel**
  * Human-readable label for notifications & menus.
* **Location** (`vector3(x, y, z)`)
  * Position where the **job menu** can be opened.
* **Blip**
  * `Enabled` – enable/disable map blip.
  * `Sprite` – blip icon ID.
  * `OffDutyColor` – color when off duty.
  * `OnDutyColor` – color when on duty.
  * `Name` – label on the map.
* **Chat**
  * `Enabled` – enable job-only chat for this job.
  * `Label` – prefix used in job chat messages.
* **Inventory**
  * `Label` – name of the job stash.
  * `Capacity` – stash capacity (items/weight, depending on your inventory setup).
* **BossRank**
  * Grade that counts as **boss** (management access).
* **InventoryOpen**
  * Minimum grade required to open job stash.
* **JobMinimumGrade**
  * Grade assigned when hiring a new employee.
* **Webhook**
  * Discord webhook URL for logs (hire, fire, duty, etc.).
  * Leave empty `''` to disable logging.

***

#### Locales / Translations 🌐 <a href="#locales-translations" id="locales-translations"></a>

`Config.Locales` holds translated strings.

To add a new language:

1. Copy an existing locale entry (e.g. `['en']`).
2. Paste as a new key, e.g. `['fr'] = { ... }`.
3. Translate all values.
4. Set:

```lua
Config.Language = 'fr'
```

> 🚨 Do **not** remove keys from the locale tables. The script expects them to exist.

```lua

---## Page 3 — Public API (Exports & Events) 🧩

---# Public API (Exports & Events) 🧩

---This page explains how **other scripts** can interact with codex_society.

---✅ You can safely share this with customers.  
---❌ No server/client source code is exposed; only public interfaces are shown.

---## Getting the Lab Library 📚

---Most examples use the **Lab lib** from `codex_core`.

---### Client-side

local Lab = exports['codex_core']:getLibClient()
```

**Server-side**

```lua
local Lab = exports['codex_core']:getLibServer()
```

Lab typically provides helpers like `Lab.GetJob()` and `Lab.GetJobGrade()`.

***

#### Client Event: Open Job Inventory 📦 <a href="#client-event-open-job-inventory" id="client-event-open-job-inventory"></a>

Use this to open the **job stash** of the player’s current job.

```lua
local Lab = exports['codex_core']:getLibClient()

TriggerServerEvent('codex_society:openInventory', Lab.GetJob())
```

* Sends the player’s job name to the server.
* Server opens the **configured job inventory** for that job.

✅ **Use this when:**

* You build your own job menu.
* You want a custom keybind to open the job stash.

***

#### Server Export: GetAccountMoney 🏦 <a href="#server-export-getaccountmoney" id="server-export-getaccountmoney"></a>

Read the current **society balance** for a job.

```lua
local amount = exports['codex_society']:GetAccountMoney(jobName)
```

* **jobName**: string, e.g. `'saloonval'`, `'doctor'`, `'sheriff'`
* **Returns**: number – society money stored for that job.

**Example**

```lua
local Lab = exports['codex_core']:getLibServer()

local jobName = Lab.GetJob(source)
local accountMoney = exports['codex_society']:GetAccountMoney(jobName)

print(('[codex_society] %s balance: %s'):format(jobName, accountMoney))
```

🔍 **Recommended usage:** Use this export for **checks only**, like:

* Check if a society can afford a purchase.
* Display society money in a custom UI.
* Generate statistics or logs.

***

#### Server Export: DepositAccountMoney 💰 <a href="#server-export-depositaccountmoney" id="server-export-depositaccountmoney"></a>

Deposit money **into** a job’s society account.

```lua
exports['codex_society']:DepositAccountMoney(jobName, amount)
```

* **jobName**: string – job identifier (must exist in `Config.Jobs`).
* **amount**: number – how much to add.

**Example**

```lua
local jobName = 'saloonval'
local reward = 50

exports['codex_society']:DepositAccountMoney(jobName, reward)
```

✅ **Use cases:**

* Rewards from job-specific missions.
* Business income going into a shared company safe.
* Event rewards that should benefit the entire job, not just one player.

> ⚠️ Important: `DepositAccountMoney` only affects the **society account**, not the player’s cash/inventory. You are responsible for managing personal money in your own scripts.

***

#### Summary 🧾 <a href="#summary" id="summary"></a>

Available public interfaces (for customers):

* **Client**
  * `TriggerServerEvent('codex_society:openInventory', jobName)`
* **Server**
  * `exports['codex_society']:GetAccountMoney(jobName)` → number
  * `exports['codex_society']:DepositAccountMoney(jobName, amount)` → deposit into society account

These are designed to be used for **checks and controlled interactions only**, without exposing private logic.

```lua

---## Page 4 — Examples, FAQ & Changelog 📚

---# Examples, FAQ & Changelog 📚

---This page shows **practical examples**, common questions, and a summary of changes.


---## Practical Examples 🧪

---### 1. Society Earns a Cut from Sales (Server)

---A saloon sale where **80%** goes to the society account and **20%** to the player.

local Lab = exports['codex_core']:getLibServer()

RegisterNetEvent('my_saloon:saleCompleted', function(jobName, salePrice)
    local src = source

    -- Player reward (handle with your own money system)
    local playerShare = math.floor(salePrice * 0.2)
    -- Society reward
    local societyCut = math.floor(salePrice * 0.8)

    -- Add to society account
    exports['codex_society']:DepositAccountMoney(jobName, societyCut)

    -- Example: notify player (using your notification system)
    TriggerClientEvent('codex-core:notification', src,
        ('You earned $%s, society earned $%s'):format(playerShare, societyCut),
        4000,
        'success'
    )
end)
```

***

**2. Check Society Balance Before an Upgrade (Server)**

Require the job to have enough society money to purchase an upgrade.

```lua
RegisterNetEvent('my_business:buyUpgrade', function(jobName)
    local src = source

    local price = 200
    local societyMoney = exports['codex_society']:GetAccountMoney(jobName)

    if societyMoney >= price then
        -- Do your own logic:
        --  • Mark upgrade as bought (DB / config)
        --  • Optionally adjust society money using your own DB logic
        --  • Give benefits to job members

        TriggerClientEvent('codex-core:notification', src,
            ('Upgrade purchased for $%s'):format(price),
            4000,
            'success'
        )
    else
        TriggerClientEvent('codex-core:notification', src,
            'Your society account does not have enough money.',
            4000,
            'error'
        )
    end
end)
```

> 🧠 The export here is used purely for a **check** before running your own logic.

***

**3. Custom Keybind to Open Job Stash (Client)**

Open the job stash when the player presses **H** near a specific location.

```lua
local Lab = exports['codex_core']:getLibClient()
local stashCoords = vector3(-313.49, 804.9, 118.98)

Citizen.CreateThread(function()
    while true do
        Citizen.Wait(0)

        local ped = PlayerPedId()
        local coords = GetEntityCoords(ped)
        local dist = #(coords - stashCoords)

        if dist < 2.0 then
            -- Show a prompt with your own system if you want

            if IsControlJustReleased(0, 0x24978A28) then -- H
                TriggerServerEvent('codex_society:openInventory', Lab.GetJob())
            end
        end
    end
end)
```

This uses the **same society stash** as the main script. No duplicate inventories.

***

#### FAQ ❓ <a href="#faq" id="faq"></a>

**“Players can’t open the job menu.”**

Check:

* The player’s job exists in `Config.Jobs`.
* The coordinates in `Config.Jobs[job].Location` are correct.
* The player is within `Config.MenuDistance`.
* No other script is blocking the menu key.

***

**“Society account is always 0.”**

* Confirm `insert.sql` was imported correctly.
* Make sure you use the **correct job name** when calling exports.
* Ensure that job is configured in `Config.Jobs`.
* Check that your own scripts are actually calling `DepositAccountMoney`.

***

**“Job chat isn’t working.”**

* Set `Config.Jobs[job].Chat.Enabled = true`.
* Make sure players use the correct chat command (`Config.Commands.Chat`).

***

**“Can I change salary per grade?”**

Yes. In `Config.SalaryJobs`:

```lua
Config.SalaryJobs = {
    ['doctor'] = {
        [0] = 15,
        [1] = 25,
    },
}
```

Each grade (`[0]`, `[1]`, etc.) can have a different amount.

***

#### Changelog 📝 <a href="#changelog" id="changelog"></a>

**v1.0**

* ➕ Added `mega_nplayerselector` dependency for hiring.
* ➕ Integrated new input menu resource `fx-input`.
* 🐛 Fixed multiple reported bugs.
* 🔧 Added `JobMinimumGrade` per job in config.

***

**v1.1**

* 🔁 Migrated all database queries to `oxmysql`.
* ⚙️ Optimized server-side performance & query handling.
* ⚡ Improved **Manage Employees** menu refresh speed.
* 🐛 Fixed additional reported bugs and edge cases.
