# BANKING V2

## Overview

Risk Banking V2 is a complete banking solution that provides:

**Core Features:**

* **ATM & Bank system:** Separate feature sets for ATMs and placed bank locations
* **PIN security:** 4-digit PIN protection with hint system after failed attempts
* **Card requirement:** Optional inventory item check before opening the UI
* **Deposit, withdraw & transfer:** Full transaction system with configurable limits
* **Transaction history:** Last 25 transactions per player stored in database
* **Loan system:** Multiple loan tiers with installments, penalties and force collection
* **Savings accounts:** Interest-bearing savings plans with configurable target amounts
* **Discord webhooks:** Full logging for every action across separate webhook channels
* **Multi-framework:** Works with ESX, QBCore and QBox (auto-detected)

**User Access:**

* ✅ You have access to: `config.lua` and `discord.lua`
* ❌ You do NOT have access to: `client.lua`, `server.lua`

All configuration is done through the config files. Backend logic is protected.

***

### ⚠️ ATM Placement (READ THIS FIRST!)

**YOU MUST PLACE ATM LOCATIONS IN-GAME OR THE SCRIPT WILL HAVE NO INTERACTION POINTS!**

```
/atm        — place a bank location at your current position (admin only)
/deleteatm  — delete the nearest bank location within 5 meters (admin only)
```

**Without placed locations:**

* No markers, blips or interaction points appear on the map
* Players cannot open the banking UI
* ATM props (if enabled) still work independently

**How to set up after installing:**

1. Join the server as an admin
2. Walk to your desired bank location
3. Type `/atm` to place it
4. Repeat for each bank location
5. Locations save automatically — no restart needed

**Common mistakes:**

* ❌ Forgetting to place any locations → Nothing appears on the map
* ❌ Placing locations inside walls → Players can't reach the interaction point
* ✅ Place locations in front of bank counters or ATM props, test by walking up as a regular player

***

### General Configuration

```lua
Config.Debug  = false  -- true = enable debug prints in server/client console
Config.Locale = 'en'   -- language: 'en', 'de', 'es', 'fr', 'pt', 'ru', 'tr', 'pl', 'it', 'nl', 'cs', 'ro'
```

```lua
-- Require a card item in inventory to open the ATM
Config.RequireCard = true
Config.CardItem    = 'bread'  -- item name must match your inventory system exactly
```

```lua
-- Require players to enter a 4-digit PIN before accessing the UI
Config.UsePin = true
Config.PinHint = {
    enabled            = true,  -- true = show a hint after X failed attempts
    attemptsBeforeHint = 3,     -- how many wrong attempts before the hint appears
}
```

***

### Transaction Limits

```lua
Config.MinDeposit  = 1        -- minimum deposit amount per transaction
Config.MaxDeposit  = 1000000  -- maximum deposit amount per transaction
Config.MinWithdraw = 1        -- minimum withdrawal amount per transaction
Config.MaxWithdraw = 1000000  -- maximum withdrawal amount per transaction
Config.MinTransfer = 1        -- minimum transfer amount per transaction
Config.MaxTransfer = 1000000  -- maximum transfer amount per transaction
```

***

### ATM & Bank Locations

```lua
-- How close a player must be to interact with a placed location
Config.ATMDistance = 1.0

-- Also detect nearby ATM prop models (in addition to placed locations)
Config.ATMUseProps = true

-- Prop model names to detect (only used if ATMUseProps = true)
Config.ATMProps = {
    'prop_atm_03',
    'prop_fleeca_atm',
    'prop_atm_01',
    'prop_atm_02',
}
```

**ATM vs Bank:**

| Feature                       | ATM prop     | Placed bank location |
| ----------------------------- | ------------ | -------------------- |
| Deposit / Withdraw / Transfer | ✅            | ✅                    |
| Loans                         | Configurable | ✅                    |
| Savings                       | Configurable | ✅                    |
| Settings / PIN change         | Configurable | ✅                    |

```lua
-- Features visible ONLY at placed bank locations, not at ATM props
Config.BankOnly = {
    savings  = false,  -- true = savings tab only at bank
    loans    = true,   -- true = loans tab only at bank
    settings = true,   -- true = settings tab only at bank
}
```

***

### Target System

```lua
Config.Target = {
    useOxTarget = false,                           -- true = use ox_target (disables proximity E-key)
    useQBTarget = false,                           -- true = use qb-target (disables proximity E-key)
    icon        = 'fa-solid fa-building-columns',  -- FontAwesome icon shown in target menu
    distance    = 2.0,                             -- interaction distance for target zones/models
}
```

**Mode comparison:**

| Mode       | Interaction method                    |
| ---------- | ------------------------------------- |
| Default    | Walk near location, press E           |
| ox\_target | Look at zone, select from target menu |
| qb-target  | Look at zone, select from target menu |

Only enable one target system. Enabling `useOxTarget` or `useQBTarget` disables the default E-key proximity interaction.

***

### Marker Configuration

```lua
Config.Marker = {
    enabled      = true,   -- true = show a 3D marker above placed locations
    type         = 21,     -- marker shape (see docs.fivem.net/docs/game-references/markers/)
    scale        = vector3(0.4, 0.4, 0.4),
    color        = { r = 255, g = 255, b = 0, a = 180 },  -- RGBA
    bobUpAndDown = false,
    rotate       = false,
    zOffset      = 0.0,    -- height offset above ground
    drawDistance = 13.0,   -- meters at which the marker starts rendering
}
```

Disable markers when using ox\_target or qb-target — they render their own zone indicators.

**Marker type reference:** <https://docs.fivem.net/docs/game-references/markers/>

***

### Blip Configuration

```lua
Config.Blip = {
    enabled    = true,
    sprite     = 108,     -- 108 = bank, 207 = atm, 277 = dollar
    color      = 2,       -- 2 = green, 5 = yellow, 1 = red
    scale      = 0.8,
    name       = 'BANK',  -- label shown on map when hovering the blip
    shortRange = true,    -- true = only visible on minimap when nearby
}
```

**Blip sprite reference:** <https://docs.fivem.net/docs/game-references/blips/>

***

### Admin Commands

```lua
Config.AdminCommands = {
    permission  = 'admin',      -- who can use admin commands: 'admin', 'mod', 'all'
    placeATM    = 'atm',        -- place a bank location at your position: /atm
    deleteATM   = 'deleteatm',  -- delete nearest location within 5m: /deleteatm
    banLoans    = 'banloans',   -- ban a player from loans: /banloans [id] [days|perm]
    unbanLoans  = 'unbanloans', -- unban a player from loans: /unbanloans [id]
}
```

**Loan ban examples:**

```
/banloans 5 7       — ban player ID 5 from loans for 7 days
/banloans 5 perm    — permanently ban player ID 5 from loans
/unbanloans 5       — remove loan ban from player ID 5
```

***

### Loan System

```lua
Config.MaxMissedPayments         = 3   -- missed installments before full loan is auto-deducted
Config.LoanLockoutDays           = 7   -- days banned from new loans after auto-deduction
Config.LoanPaymentWarningMinutes = 10  -- minutes before due date to show a warning (0 = disabled)
```

#### Loan Tiers

```lua
Config.Loans = {
    {
        id           = 'starter',
        amount       = 20000,     -- loan amount in $
        commission   = 0.08,      -- fee on top of loan (0.08 = 8%)
        duration     = 1,         -- total repayment window
        durationUnit = 'minutes', -- 'minutes' or 'hours'
        payments     = 3,         -- number of installments
        penaltyRate  = 0.10,      -- % penalty added to balance if overdue (0.10 = 10%)
    },
    {
        id           = 'silver',
        amount       = 50000,
        commission   = 0.12,
        duration     = 96,
        durationUnit = 'hours',
        payments     = 4,
        penaltyRate  = 0.12,
    },
}
```

**How loans work:**

1. Player opens bank, selects a loan tier and confirms
2. Loan amount is added to bank balance, commission is added to repay amount
3. Player makes installment payments with the **PAY** button
4. If a payment is missed, `penaltyRate` is added to the remaining balance
5. After `MaxMissedPayments` missed installments, the full remaining balance is auto-deducted from bank
6. Player is locked out of new loans for `LoanLockoutDays` days after auto-deduction

**How installments are calculated:**

```
Repay amount  = loan amount + (loan amount × commission)
Per payment   = repay amount ÷ payments
```

***

### Savings System

```lua
Config.Savings = {
    {
        id                    = 'bronze',
        targetAmount          = 50000,      -- savings goal in $ required before withdrawal is unlocked
        interestRate          = 0.02,       -- interest per interval (0.02 = 2%)
        interestIntervalHours = 24,         -- hours between each interest payout
        minDeposit            = 100,        -- minimum single deposit in $
        maxDeposit            = 10000,      -- maximum single deposit in $
    },
    {
        id                    = 'silver',
        targetAmount          = 150000,
        interestRate          = 0.03,
        interestIntervalHours = 24,
        minDeposit            = 500,
        maxDeposit            = 25000,
    },
    {
        id                    = 'gold',
        targetAmount          = 500000,
        interestRate          = 0.05,
        interestIntervalHours = 24,
        minDeposit            = 1000,
        maxDeposit            = 100000,
    },
}
```

**How savings work:**

1. Player opens bank, selects a savings plan and starts it
2. Player deposits money from bank into the savings account
3. Interest is automatically added every `interestIntervalHours`
4. Once the balance reaches `targetAmount` the plan is marked complete
5. Player can withdraw the full balance only after the target is reached

**Savings tiers comparison:**

| Tier   | Target   | Interest | Interval |
| ------ | -------- | -------- | -------- |
| Bronze | $50,000  | 2%       | 24h      |
| Silver | $150,000 | 3%       | 24h      |
| Gold   | $500,000 | 5%       | 24h      |

***

### Notify System

```lua
Config.UseCustomHelpNotify = true  -- true = use custom helpnotify below, false = native GTA help text

Config.Functions = {
    ['helpnotify'] = function(key, text)
        if key == 38 then key = 'E' end
        exports['risk-notify']:HelpNotify(key, text)
    end,
}
```

To use a different notify resource, replace the export call with your system's equivalent.

***

### Discord Webhook Setup

Open `discord.lua` and configure your webhooks:

```lua
DiscordConfig.Enabled   = false        -- true = enable all webhook logging
DiscordConfig.BotName   = 'Risk Banking'
DiscordConfig.BotAvatar = ''           -- URL to bot avatar image (leave empty for default)

DiscordConfig.Webhooks = {
    main     = 'https://discord.com/api/webhooks/...',  -- deposits, withdrawals, transfers, loans
    settings = 'https://discord.com/api/webhooks/...',  -- PIN creation, PIN changes
    savings  = 'https://discord.com/api/webhooks/...',  -- savings start, deposits, interest
}
```

**What gets logged per channel:**

| Channel    | Events                                                                                   |
| ---------- | ---------------------------------------------------------------------------------------- |
| `main`     | Deposit, withdraw, transfer, loan taken, loan repaid, loan force collected, loan penalty |
| `settings` | PIN created, PIN changed                                                                 |
| `savings`  | Savings started, savings deposit, savings withdrawal, interest added                     |

**Embed colors** are configurable per event type in `DiscordConfig.Colors`. Values are decimal color codes (e.g. `3066993` = green, `15158332` = red).

***

### Troubleshooting

#### No interaction points appear on the map

**Cause:** No bank locations placed yet **Solution:** Join as admin and type `/atm` at each location you want

#### ATM props not triggering interaction

**Cause 1:** `Config.ATMUseProps = false` **Solution:** Set `ATMUseProps = true` and add the prop model name to `Config.ATMProps`

**Cause 2:** Using ox\_target or qb-target without registering prop models **Solution:** Target systems auto-register prop models on resource start — ensure the resource is started correctly

#### PIN prompt not appearing

**Cause:** `Config.UsePin = false` **Solution:** Set `UsePin = true` — players will be prompted to create a PIN at the bank the first time

#### Player can't open ATM — card error

**Cause:** `Config.RequireCard = true` but player doesn't have the item **Solution:** Either set `RequireCard = false` or give the player the item defined in `Config.CardItem`

#### Loan payment not registering

**Cause:** Player does not have enough bank balance for the installment amount **Solution:** Player must deposit cash to bank first, then pay the installment

#### Savings withdrawal locked

**Cause:** Balance has not reached `targetAmount` yet **Solution:** Working as intended — withdrawal only unlocks when the savings goal is reached

#### Webhook not sending

**Cause 1:** `DiscordConfig.Enabled = false` **Solution:** Set `Enabled = true` in `discord.lua`

**Cause 2:** Webhook URL is empty or invalid **Solution:** Paste your full Discord webhook URL into the matching `DiscordConfig.Webhooks` field

#### `/banloans` or `/unbanloans` does nothing

**Cause:** `Config.AdminCommands.permission` set to `'admin'` but your group doesn't have ACE `group.admin` **Solution:** Either add ACE permission or set `permission = 'all'` for testing

***

### Quick Start Checklist

**Server setup:**

* \[ ] Configure `Config.Locale` if not using English
* \[ ] Set `Config.CardItem` to your server's bank card item name (or disable `RequireCard`)
* \[ ] Configure transaction limits to match your server's economy
* \[ ] Set `Config.BankOnly` features based on your preference
* \[ ] Configure `Config.AdminCommands.permission` to match your admin group

**ATM placement:**

* \[ ] Join server as admin
* \[ ] Walk to each bank / ATM location
* \[ ] Type `/atm` to place
* \[ ] Verify blips and markers appear on the map
* \[ ] Test E-key interaction as a regular player

**Loans:**

* \[ ] Adjust `Config.Loans` tiers to match your server's economy
* \[ ] Set `Config.MaxMissedPayments` and `Config.LoanLockoutDays`
* \[ ] Enable `Config.LoanPaymentWarningMinutes` for player reminders

**Savings:**

* \[ ] Adjust `Config.Savings` tiers and target amounts
* \[ ] Set `interestIntervalHours` based on how active your server is

**Discord webhooks:**

* \[ ] Set `DiscordConfig.Enabled = true` in `discord.lua`
* \[ ] Create webhook channels in your Discord server
* \[ ] Paste webhook URLs into `DiscordConfig.Webhooks`
* \[ ] Test by making a deposit and checking the Discord channel

**Test everything:**

* \[ ] Open ATM as player without card — verify card error appears
* \[ ] Create PIN at bank — verify PIN prompt appears on next visit
* \[ ] Deposit, withdraw and transfer — verify balance updates and Discord logs
* \[ ] Take a loan — verify amount is added to bank
* \[ ] Make a loan payment — verify remaining balance decreases
* \[ ] Start a savings plan — verify interest is added after the configured interval
* \[ ] Withdraw completed savings — verify balance is released


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://risk-scripts.gitbook.io/risk-scripts/scripts/banking-v2.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
