Skip to content

Instruction

This script allows you to create and manage various markets within your server. It provides a flexible framework to define markets, making a market truly what you want.

Description

This documentation will guide you through setting up and configuring new markets.

On going

This documentation probably doesn't include everything. I'll try to add more details over time.

Preview

Configs

In this section, I'll explain the structure of config files and how they work.

config.shared.lua

ConfigDescription
MagicTouchFlag for dev mode. Set to true to see zones
inventory_nameName of the inventory you're using.
targetSupports two values, ox_target and interactionMenu. All required code is open if you're using other script

TIP

inventory_name is used to locate image files and to check correct export in validate_canAddItem function (server/accessible/purchase.lua)

config.server.lua

ConfigDescription
level.max_xpMaximum XP value players can reach
level.xp_per_levelXP required per level
global_min_level_direct_callMinimum level required to directly call blackmarket NPCs
deaddropsDefine new dead drop zones. The system will randomly select and assign these to players
blackmarketsLocations where blackmarket NPCs will randomly appear for players
plug_npcSettings related to the plug NPC (middleman)
privilege_typeType of privilege to check. Options: licence, discord, fivem, licence2, ip
adminsWhitelist someone for admin operations within the script

config.server.autogen.lua

You can ignore this file! it's generated by admin menu and gizmo system within the script.

config.client.lua

It's a placeholder. I might add new configs but as of right now it's empty.

How to make new quests?

First, let's create a new file, for better organization.

For example, if you're making new quests for the iron_exchange black market, you could name the file:

plaintext
quests/quest.iron_exchange.lua

Structure

FieldDescription
labelThe display name of the quest
descDescription of the quest (You can use HTML)
maxCompletedHow many times quest should be completed until player can claim their rewards
rewardsTable containing the rewards for completing the quest
penalties(Optional) Table containing the penalties for failing the quest. (It doesn't do anything 😃)

TIP

Reward types: money, reputation or item

lua
RegisterQuest("smuggling_quest_1", {
    label = "The Covert Operation",
    desc = [[
    Listen up, </br></br>
    ]],
    maxCompleted = 100,
    rewards = {
        {
            name = 'cash',
            type = 'money',
            label = 'Cash',
            amount = 100,
        },
        {
            name = 'reputation',
            type = 'reputation',
            label = 'Reputation',
            amount = 5,
        }
    }
})

How do i add new payphones

In this folder configs/payphones, we create and register payphones.

TIP

Ignore these three lines, as they inject the new configurations into the main config.

lua
Config = Config or {}
Config.payphones = {}
local payphones = Config.payphones

Here’s how to add payphones:

lua
Config = Config or {}
Config.payphones = {}
local payphones = Config.payphones

payphones[#payphones + 1] = {
    model = 'prop_phonebox_03',
    position = vector4(432.514282, -942.474731, 27.128174, 15.748032)
}
CodeDescription
modelThe model of the payphone
positionThe position of the payphone vector4 (x, y, z, heading)

How to create new retail markets?

In this script, we have two types of markets: retail and blackmarket. These markets share a similar syntax but have some differences too, especially in how they are registered.

We have two folders: configs/markets for retail markets and configs/blackmarkets for black markets.

To register markets, we use RegisterMarket(market_info), and for black markets, we use RegisterBlackmarket(market_info).

Retail

lua
-- markets/247supermarket.lua
local ltdgasoline = {
    name = 'ltdgasoline',
    label = "LTD Gasoline",
    -- ... 
}

RegisterMarket(ltdgasoline)

Black market

lua
-- blackmarkets/iron_exchange.lua
local preset = {
    name = 'iron_exchange',
    label = "Iron Exchange",
    -- ... 
}

RegisterBlackmarket(ltdgasoline)

Attributes

These are primary attributes of a market.

FieldTypeMarketDescription
namestringsharedUnique identifier for the market. It must be unique it's important
labelstringsharedDisplay name of the market
useStockbooleanretailIndicates if stock management is enabled for this market
lua
local preset = {
    name = 'iron_exchange',
    label = "Iron Exchange",
    useStock = true
}
npc

Details about the NPC associated with the market.

FieldTypeMarketDescription
modelstringsharedThe model of the NPC
scenariostringretailThe scenario in which the NPC will be placed
firstnamestringblackmarketFirst name of the NPC
lastnamestringblackmarketLast name of the NPC
personalitystringblackmarketLocale id
lua
local preset = {
    name = 'iron_exchange',
    label = "Iron Exchange",
    useStock = true,
    npc = {
        model = 'mp_m_shopkeep_01',
        scenario = 'WORLD_HUMAN_STAND_MOBILE',
    },
}
target

Specifies the target settings for the market interaction.

FieldTypeDescription
radiusnumberThe interaction radius around the target
iconstringThe icon used for the target
labelstringThe interaction label for the target
lua
local preset = {
    name = 'iron_exchange',
    label = "Iron Exchange",
    useStock = true,
    npc = {
        model = 'mp_m_shopkeep_01',
        scenario = 'WORLD_HUMAN_STAND_MOBILE',
    },
    target = {
        radius = 0.5,
        icon = 'fas fa-shopping-basket',
        label = 'Open Shop',
    },
}
blip

Retail only

Defines blip settings for the market.

FieldTypeDescription
spritenumberThe sprite for the blip
scalenumberThe scale of the blip
colornumberThe color ID for the blip
lua
local preset = {
    name = 'iron_exchange',
    label = "Iron Exchange",
    useStock = true,
    npc = {
        model = 'mp_m_shopkeep_01',
        scenario = 'WORLD_HUMAN_STAND_MOBILE',
    },
    target = {
        radius = 0.5,
        icon = 'fas fa-shopping-basket',
        label = 'Open Shop',
    },
    blip = {
        sprite = 52,
        scale = 0.6,
        color = 0,
    },
}
categories

Lists the categories available in the market.

FieldTypeDescription
categoriestableList of categories. Example: { 'normal' }
lua
local preset = {
    name = 'iron_exchange',
    label = "Iron Exchange",
    useStock = true,
    npc = {
        model = 'mp_m_shopkeep_01',
        scenario = 'WORLD_HUMAN_STAND_MOBILE',
    },
    target = {
        radius = 0.5,
        icon = 'fas fa-shopping-basket',
        label = 'Open Shop',
    },
    blip = {
        sprite = 52,
        scale = 0.6,
        color = 0,
    },
    categories = {
        'iron_exchange'
    },
}
coords

Retail only

If we use useStock = true, each market will have its own stock and won't share stock with other markets. Therefore, we don't need to define multiple markets, a single market like 247supermarket is enough!

Specifies the coordinates where the market is located.

FieldTypeDescription
coordstableList of vector4 coordinates for market locations
lua
local preset = {
    name = 'iron_exchange',
    label = "Iron Exchange",
    useStock = true,
    npc = {
        model = 'mp_m_shopkeep_01',
        scenario = 'WORLD_HUMAN_STAND_MOBILE',
    },
    target = {
        radius = 0.5,
        icon = 'fas fa-shopping-basket',
        label = 'Open Shop',
    },
    blip = {
        sprite = 52,
        scale = 0.6,
        color = 0,
    },
    categories = {
        'iron_exchange'
    },
    coords = {
        vector4(-47.02, -1758.23, 28.42, 45.05),
        vector4(-706.06, -913.97, 18.22, 88.04),
        vector4(-1820.02, 794.03, 137.09, 135.45),
        vector4(1164.71, -322.94, 68.21, 101.72),
        vector4(1697.87, 4922.96, 41.06, 324.71),
    }
}
restrictions (Optional)

Optional restrictions for accessing the market.

FieldTypeDescription
identifierstableList of identifiers allowed to access the market
jobtableJob restrictions for accessing the market
gangtableGang restrictions for accessing the market
itemstringItem required to access the market
customfunctionCustom function for additional checks
lua
local preset = {
    name = 'iron_exchange',
    label = "Iron Exchange",
    useStock = true,
    npc = {
        model = 'mp_m_shopkeep_01',
        scenario = 'WORLD_HUMAN_STAND_MOBILE',
    },
    target = {
        radius = 0.5,
        icon = 'fas fa-shopping-basket',
        label = 'Open Shop',
    },
    blip = {
        sprite = 52,
        scale = 0.6,
        color = 0,
    },
    categories = {
        'iron_exchange'
    },
    coords = {
        vector4(-47.02, -1758.23, 28.42, 45.05),
        vector4(-706.06, -913.97, 18.22, 88.04),
        vector4(-1820.02, 794.03, 137.09, 135.45),
        vector4(1164.71, -322.94, 68.21, 101.72),
        vector4(1697.87, 4922.96, 41.06, 324.71),
    },
    restrictions = {
        identifiers = {
            'HLP78991'
        }
    }
}

I Don't Get Any Emails

The only interaction of this script with phones is sending emails. If you need to integrate it with another phone system, you can edit the file located at lua/client/accessible/mailer.lua and use your phone's exports to show emails to players.

Editing the File

Here's how to modify the script to use another phone system to send mails:

  1. Open the mailer.lua file located at lua/client/accessible/mailer.lua.
  2. Locate the following code block:
lua
RegisterNetEvent('keep-blackmarket:client:mail->send', function(data)
    if data.coords then
        local x, y, z = table.unpack(data.coords)
        local streetHash = GetStreetNameAtCoord(x, y, z)
        local streetName = GetStreetNameFromHashKey(streetHash)

        data.message = replace(data.message, 'streetName', streetName)
    end

    if Config.MagicTouch then
        Harmony.CNotify('Email', data.message, 'info', 8000)
    else
        TriggerServerEvent('qb-phone:server:sendNewMail', {
            sender = data.sender,
            subject = data.subject,
            message = data.message,
            button = {}
        })
    end
end)
  1. Replace the server event if statement with your phone system's export.
lua
RegisterNetEvent('keep-blackmarket:client:mail->send', function(data)
    if data.coords then
        local x, y, z = table.unpack(data.coords)
        local streetHash = GetStreetNameAtCoord(x, y, z)
        local streetName = GetStreetNameFromHashKey(streetHash)

        data.message = replace(data.message, 'streetName', streetName)
    end

    exports['myPhone']:sendMail({
        sender = data.sender,
        subject = data.subject,
        message = data.message,
        button = {}
    })
end)

Commands

This is the only command within the script. It opens the admin menu if you have admin privileges here:

edit files

Admin menu client code is accessible in this path lua/client/accessible/admin.lua

With this menu you can do these:

  1. Add new black market locations
  2. Add new dead drop locations
  3. Give xp to a player
plaintext
/blackmarket

Support

If you need any help or have any questions about our products, please join our discord channel: https://discord.gg/ccMArCwrPV