Configuration

Current configuration reference for Oxide Vending.

Every setting in oxide-vending, explained. All settings live in the config/ folder — open the files with any text editor, change the values, save, and restart the resource. One exception: the dashboard map mode (Config.MapMode) is only read on the first start and is saved in your database after that; change it with a command (see Dashboard map).

General

config/config.lua

Config.Debug = false
Config.UseHudAccent = true

Set Config.Debug to true to make the resource print extra information to the F8 console and server console while you test. Leave it false on a live server.

Config.UseHudAccent: the key caps of the placement hint (E, Backspace, Scroll) use your server's accent colour from Oxide HUD, set in Oxide HUD's Config.Theme (see Accent Colour). false keeps them white. Without Oxide HUD, or with no accent set there, nothing changes.

Business rules

Config.Business = {
    MaxMachinesPerBusiness = 10,
    MaxEmployees = 5,
    RegistrationFee = 5000,
    AllowMultipleBusinesses = false,
    OnePerAccount = false,
    DefaultMachineCapacity = 400,
    MaxBusinesses = 0,
}
  • MaxMachinesPerBusiness / MaxEmployees: only used if you turn the level system off — while leveling is on, the business's level decides these limits instead.
  • RegistrationFee: what it costs to start a business.
  • AllowMultipleBusinesses: set true to let one character own several businesses.
  • OnePerAccount: set true to allow only one business per player account, even across their different characters.
  • DefaultMachineCapacity: a fallback storage size, only used if a machine's type can't be found in the config.
  • MaxBusinesses: a server-wide cap on the total number of businesses. 0 means no cap.

Employee permissions

Config.Permissions = {
    owner = { 'manage', 'stock', 'collect', 'place', 'remove', 'hire', 'fire', 'pricing', 'withdraw', 'deposit', 'view_balance' },
    manage = { 'stock', 'collect', 'place', 'remove', 'pricing', 'deposit', 'view_balance' },
    collect = { 'collect', 'view_balance' },
    stock = { 'stock' },
}

Each role is a list of things that role is allowed to do. You can add or remove permissions from any role, but keep the role names as they are.

view_balance lets an employee see the business account balance and the transaction history, in the business menu and on the dashboard. Without it (the stock role by default), both are hidden.

Machine placement

Config.Placement = {
    MaxDistanceFromPlayer = 10.0,
    MinDistanceBetweenMachines = 2.0,
}
  • MaxDistanceFromPlayer: how far away (in meters) a player can place a machine from where they stand.
  • MinDistanceBetweenMachines: how much space must be between two machines.

No-placement zones

Config.BlockedZones = {
    -- { name = 'police_station', coords = vector3(x, y, z), radius = 50.0 }
}

Add areas where machines can never be placed. Each zone is a point on the map and a radius around it in meters.

Pricing

Config.Pricing = {
    MinMarkup = 0.8,
    MaxMarkup = 3.0,
    DefaultMarkup = 1.5,
}

How far an owner's selling price may stray from an item's base price. 0.8 means 80% of base price, 3.0 means triple. DefaultMarkup is what newly stocked items are priced at before the owner adjusts them.

These three are only the fallback — while the level system is on, each business level has its own price range (see Progression).

Wholesale (bulk ordering)

Config.Wholesale = {
    Enabled = true,
    MarkupPercent = 0.20,
    DeliveryTime = 300,
    MinOrder = 10,
    DeliveryCheckInterval = 30,
}
  • MarkupPercent: how much extra businesses pay over the catalog's wholesale price (0.20 = 20%). Higher business levels reduce this.
  • DeliveryTime: how long an order takes to arrive, in seconds (300 = 5 minutes, 0 = instant).
  • MinOrder: a global minimum-order floor applied to every order. The effective minimum for any catalog item is the larger of that item's own minQty and this value.
  • DeliveryCheckInterval: how often the server checks whether pending orders have arrived, in seconds. You shouldn't need to change this.

config/wholesale.lua

Config.WholesaleCatalog is the bulk-order menu, grouped by machine type. Each entry looks like:

{ item = 'water', basePrice = 3, minQty = 10, label = 'Water Bottle' },
  • item: the item's name in your inventory system — it must exist on your server (see Installation, step 5)
  • basePrice: the wholesale cost per unit, before the markup
  • minQty: the smallest amount of this item per order
  • label: the name shown to players

Warehouse

Config.Warehouse = {
    Enabled = true,
    Price = 50000,
    MaxCapacity = 5000,
    MaxItemTypes = 50,
    RequiredLevel = 3,
    CodeLength = 4,
    DoorLocation = vector4(-128.68, -1393.47, 28.59, 208.25),
    Interior = {
        Exit = vector4(1087.57, -3099.38, -39.0, 264.61),
        Storage = vector4(1100.98, -3101.89, -39.0, 183.82),
    },
    BucketIdStart = 1000,
}
  • Enabled: turn the whole warehouse feature on or off.
  • Price: the purchase price, paid from the business balance.
  • MaxCapacity: the most items a warehouse can hold in total.
  • MaxItemTypes: how many different items it can hold.
  • RequiredLevel: the business level needed before the warehouse can be bought (while leveling is on).
  • CodeLength: how many digits the keypad code has.
  • DoorLocation: where the warehouse door is in the world.
  • Interior.Exit / Interior.Storage: where players appear inside, and where the storage point is. These point into a GTA interior — only change them if you know what you're doing.
  • BucketIdStart: a technical setting that keeps each business's warehouse instance separate. Only change it if another script on your server also uses routing buckets numbered 1000 and up.

Pickup pallet

Config.PickupLocation = {
    Enabled = true,
    Coords = vector4(-128.35, -1416.47, 30.3, 114.55),
    PalletModel = 'bkr_prop_coke_pallet_01a',
    BoxModel = 'prop_cs_cardbox_01',
    MaxBoxes = 12,
    PickupTime = 3000,
    PickupAnimation = {
        dict = 'anim@amb@clubhouse@tutorial@bkr_tut_ig3@',
        anim = 'machinic_loop_mechandplayer',
        flags = 1,
    },
}

This is where wholesale deliveries physically appear as boxes.

  • Enabled: if false, no boxes spawn (deliveries still complete).
  • Coords: where the pallet sits.
  • MaxBoxes: how many boxes can be shown at once before positions start being reused.
  • PickupTime: how long collecting a box takes, in milliseconds (3000 = 3 seconds).
  • PickupAnimation: the animation played while collecting.

Transaction history cleanup

Config.Transactions = {
    RetentionDays = 90,
    PruneInterval = 3600,
    PruneOnStartup = true,
}

Sale records pile up over time, so old ones are deleted automatically.

  • RetentionDays: how many days of history to keep. Set to 0 to keep everything forever.
  • PruneInterval: how often the cleanup runs, in seconds (3600 = hourly).
  • PruneOnStartup: also clean up each time the resource starts.

Showroom

Config.Showroom = {
    Enabled = true,
    Location = vector3(-132.5, -1418.28, 31.3),
    Heading = 208.38,
    Blip = {
        enabled = true,
        sprite = 478,
        color = 2,
        scale = 0.7,
        label = 'Vending Machines',
    },
    NPC = {
        model = 's_m_m_lifeinvad_01',
        scenario = 'WORLD_HUMAN_CLIPBOARD',
    },
}

The showroom is the NPC players visit to register a business and buy machines. You can move it, change the map icon (Blip), or change which character model the NPC uses.

Notifications and interactions

Config.Interaction = {
    TargetDistance = 2.5,
    UseProgressbar = true,
    StockingTime = 3000,
    CollectTime = 2000,
}
  • Notifications appear wherever your server's notification resource puts them, so there are no notification settings here. The older Config.Notifications table (Position and Duration) was never read and has been removed; if your config still has it, it does nothing and you can delete it.
  • TargetDistance: how close (in meters) a player must be to interact with the showroom NPC, machines, and pickup boxes.
  • UseProgressbar: show a progress bar while stocking and collecting.
  • StockingTime / CollectTime: how long those actions take, in milliseconds.

Business dashboard

Config.Dashboard = {
    UseTablet = true,
}
  • UseTablet: if the separate oxide-tablet resource is installed and running, the dashboard opens as a "Vending" app inside that tablet instead of in its own window. /vdb opens the tablet straight to it, and players with business access also get a tile in the tablet's app list. Set this to false to keep the dashboard in its own window even when the tablet is present. Without oxide-tablet this setting does nothing.
  • If your config.lua is from an older version and has no Config.Dashboard block, the tablet is used whenever it is available.

Machine wear and repair

Config.Durability = {
    Enabled = true,
    DegradationPerSale = 0.5,
    DegradationPerNPCSale = 0.3,
    BrokenThreshold = 0,
    WarningThreshold = 20,
    RepairCosts = {
        drinks = 500,
        snacks = 400,
        general = 750,
        electronics = 1500,
    },
    DefaultRepairCost = 500,
    AllowCollectWhenBroken = true,
    DegradationVariance = 0.2,
}

Machines start at 100% durability and lose a little per sale (0.5 per player sale means roughly 200 sales before breaking).

  • WarningThreshold: the owner is notified when durability drops below this percentage.
  • BrokenThreshold: the machine breaks when durability reaches this.
  • RepairCosts: the flat repair fee per machine type.
  • AllowCollectWhenBroken: if true, owners can still take their money out of a broken machine.
  • DegradationVariance: adds a little randomness to wear (0.2 = up to ±20% per sale).

Set Enabled = false to turn wear off entirely.

Machine types

config/machines.lua

Config.MachineTypes defines what players can buy: the name, price, how many item slots each machine has, how many items fit per slot, and which GTA prop models it can look like.

Current defaults:

TypePriceSlotsItems per slotLooks
drinks$15,0008505
snacks$12,0006402
general$20,00012301
electronics$35,0006201

To add your own machine type:

  1. Add an entry to Config.MachineTypes in config/machines.lua.
  2. Give it an item whitelist in Config.ItemWhitelists (config/items.lua).
  3. Add base prices for its items in Config.ItemBasePrices.
  4. If the level system is on, add the new type to the unlockedTypes list of at least one level in config/progression.lua — otherwise nobody can ever buy it.

Items

config/items.lua

Two lists live here:

  • Config.ItemWhitelists — which item names each machine type may sell.
  • Config.ItemBasePrices — the "fair price" for each item. This anchors the allowed price range, the dashboard's price suggestions, and how the NPC economy judges whether a machine is cheap or expensive.

Every item you list must exist in your server's inventory system — see Installation step 5 for how to check per framework.

Good to know: if an item is whitelisted but has no entry in Config.ItemBasePrices, the resource treats its base price as $10.

NPC sales

config/npc_sales.lua

Config.NPCSales = {
    Enabled = true,
    TickInterval = 60,
    BaseChancePerTick = 0.05,
    MinQuantity = 1,
    MaxQuantity = 2,
    AvoidLastItem = true,
    PreferCheaperItems = true,
    RevenueMultiplier = 1.0,
    MachineTypeModifiers = { ... },
    TimeMultipliers = { ... },
    Hotzones = { ... },
    DefaultLocationMultiplier = 1.0,
    VisualFeedback = {
        Enabled = true,
        PlayerRange = 50.0,
        PedSearchRadius = 30.0,
        MachineCooldown = 30000,
    },
}

The most useful knobs:

  • Enabled: master switch for passive NPC sales.
  • TickInterval: how often (in seconds) the server gives every machine a chance to make a sale.
  • BaseChancePerTick: the starting chance per machine per tick, before location/time/price factors (0.05 = 5%).
  • AvoidLastItem: NPCs never buy a machine's very last item, so player customers always find something.
  • RevenueMultiplier: one dial to scale all NPC income up or down for your economy.
  • VisualFeedback: the cosmetic "pedestrian walks up to the machine" animations. Turning this off does not affect the income.

See NPC Sales for how the full calculation works and how to add your own busy/quiet areas (Hotzones).

Weather (config/weather.lua)

Config.WeatherIntegration = { Enabled = false, HotTemperature = 35, RainSales = 0.85, HotDrinkSales = 1.15 }

An optional weather effect on NPC sales, off by default. It needs oxide-weather, which reports the rain and temperature at each machine; with any other weather resource, or none, sales are not affected.

  • Enabled: turns the effect on.
  • RainSales: sales multiplier while it is raining at the machine (0.85 = 15% fewer sales). Allowed range 0.1 to 2.
  • HotTemperature: the temperature in °C from which drink machines sell more. Allowed range 20 to 65.
  • HotDrinkSales: sales multiplier for drink machines at or above HotTemperature (1.15 = 15% more). Allowed range 0.1 to 2.

Edit the file and restart the resource. A value outside its range is replaced by the shipped value, and the server console says which one. Another script can change these values while the server runs with the SetSetting export (see Exports → SetSetting('WeatherIntegration', values)); such a change lasts until the next restart, when the file applies again.

Competition

Config.Competition = {
    Enabled = true,
    Radius = 500.0,
    SameOwnerCompetes = false,
    MinMultiplier = 0.3,
    MaxMultiplier = 1.8,
    CheapestBonus = 1.5,
    SuggestedPriceMargin = 0.95,
    SuggestedPriceMinMarkup = 0.85,
    AnalysisCacheTime = 300,
    ShowCompetitorNames = true,
    ShowExactPrices = true,
}

When machines of the same type sit near each other, they fight over NPC customers — cheaper machines win.

  • Radius: how far apart (in meters) machines still count as competitors.
  • SameOwnerCompetes: with the default false, a business's own machines never hurt each other.
  • ShowCompetitorNames / ShowExactPrices: what the dashboard's competition page reveals about rival businesses.
  • AnalysisCacheTime: how long (in seconds) the dashboard reuses its last competition analysis before recalculating.

Business levels

config/progression.lua

Config.Progression = {
    Enabled = true,
    Levels = { ... },
    XPSources = { ... },
    Milestones = { ... },
    Notifications = {
        showXPGain = true,
        xpGainThreshold = 25,
        levelUpSound = true,
        levelUpAnimation = true,
        milestoneNotify = true,
    },
}

The level system controls machine limits, employee limits, which machine types are unlocked, the allowed price range, the wholesale discount, and the NPC revenue bonus. Set Enabled = false to switch all of that off and use the flat limits from Config.Business and Config.Pricing instead.

See Progression for the full level table and every XP value.

Dashboard map

The business dashboard's map comes from o-link (1.8.0 or newer), so it shows Cayo Perico as well as Los Santos.

config/config.lua
Config.MapMode = 'inherit'
  • 'inherit': use the map mode set for every resource in o-link (olink:mapmode <mode> in the server console).
  • 'combined': Los Santos and Cayo Perico on one map.
  • 'separate': a Mainland / Cayo Perico switch on the map.
  • 'disabled': Los Santos only.

Config.MapMode is only read on the resource's first start. After that the mode is saved in your database (oxide_settings), and editing the file changes nothing. To change it, type oxide-vending:mapmode <mode> in the server console, or /oxide-vending:mapmode <mode> in game as an admin. It applies straight away. See Admin Commands → Dashboard map command.