Price
UnknownA script by alva98
Price
UnknownHey everyone 
Today I’m releasing as-routes — a complete, fully dynamic routes/workstations system that solves the classic problem of hardcoded farming/drug scripts: you can create, edit and balance full loops ingame (farm → process → sell) without constantly touching code.
It supports ESX + QBCore and is built to be lightweight + scalable.
The ressource also takes advantage of some high performance tricks to make it as close to 0.0ms resmon on the server as possible.

Config file previewConfig = Config or {}
-- General
Config.debug = true -- enable debug prints in F8 console
Config.logLevel = "debug" -- debug | info | warn | error
Config.locale = "en-US" -- language key (see config/translations.json)
Config.framework = "auto" -- "auto" | "esx" | "qb"
-- Commands
Config.adminCommand = "routeadmin" -- command to open admin panel
Config.enableColorpickerCommand = true -- set false to disable the color picker command and UI
Config.colorPickerCommand = "routecolors" -- command to open the color picker overlay
Config.debugCommand = "routedebug" -- command to see visual debug of routes
Config.access = Config.access or {}
Config.access.admins = {
esxGroups = { admin = true, superadmin = true },
qbPermissions = { god = true, admin = true },
}
Config.access.identifiers = { -- manual identifier overrides
-- ["steam:123123123"] = true,
-- ["license:abcbacbacbacbacb"] = true,
-- ["discord:123123123123123"] = true,
}
-- ox_target Integration
Config.useOxTarget = true -- set true to use ox_target eye interactions on sell/transform/workstation NPCs
Config.useBlipCategories = true -- if true, all route blips will have their own category
Config.blipCategorys = {
farm = {
categoryId = 22,
name = "Farming",
},
sell = {
categoryId = 23,
name = "Selling",
},
transform = {
name = "Transform",
categoryId = 24,
},
workstation = {
name = "Workstation",
categoryId = 25,
}
}
-- Colors (UI theming)
Config.colors = {
primary = "#3E8BC8",
primary25 = "#3E8BC835",
primary45 = "#3E8BC865",
}
-- ================================================================
-- Item Images (same pattern as as-garage)
-- %s is replaced with the item spawn name; UI tries .webp > .png > .jpg
-- ox_inventory default:
-- ================================================================
Config.imagePattern = "https://cfx-nui-ox_inventory/web/images/%s"
Config.placeholderImage = "https://cfx-nui-ox_inventory/web/images/none.png"
Config.drawMarkerColor = "3E0F97D6" -- color for farm/sell markers; can also be set per route, AARRGGBB
-- ================================================================
-- Police Raid System
-- ================================================================
Config.policeRaid = {
enabled = true,
-- Route block: how many hours a route stays blocked after a successful raid.
-- During this time, nobody can farm/sell/transform on this route.
blockHours = 24,
-- Per-route cooldown: once a specific route has been raided, it cannot be
-- raided again for this many hours (even after blockHours expires).
-- Example: 168 = 1 week before the same route can be raided again.
raidCooldownHours = 168,
-- Global raid limit: max number of raids police can complete within
-- the last `blockHours` window across ALL routes. Prevents officers
-- from chain-raiding every route back-to-back.
-- Set to 0 or nil to disable the global limit.
maxRaidsWithinBlockHours = 2,
-- Minimum police officers online: raids can only be started when at least
-- this many players with an allowedJob are online. Prevents solo raids.
-- Set to 0 to disable this check.
minPoliceOnlineForRaid = 1,
-- Raid time restrictions: raids can only be started during these hours
-- (server real time, 24h format). Supports wrap-around (e.g. 18 to 0).
-- Remove or set to nil to allow raids at any time of day.
raidHours = { -- use 24h format: "HH:MM"
start = "06:15", -- raids allowed from (6:15 AM)
stop = "22:15", -- until 22:15 (10:15 PM)
},
raidArea = 50.0, -- if a player leaves the raid zone (is further away than 50.0 for example, the raid fails)
raidDurationSeconds = 60 * 15, -- how long the officer must survive at the raid point
clearWorkstationOnRaid = false, -- wipe all workstation data for this route on successful raid
notifyRadius = 400.0, -- meters — players within this range get the big on-screen warning
markerAboveRaidersHead = true, -- show a marker above the raiders' heads during the raid
allowedJobs = { -- job = minimum grade required, for qb, can also be a gang with minimum rank
["police"] = 1,
["sheriff"] = 1,
},
}
Config.raidMarkerType = 31 -- wolf head
Config.raidMarkerDrawDistance = 20.0 -- distance to draw the raid marker
-- ================================================================
-- Farming / Selling / Workstation Defaults
-- ================================================================
Config.defaults = {
farmTime = 5000, -- ms per farm tick (overrideable per route)
sellTime = 1000, -- ms per sell tick (overrideable per route)
farmAmount = 2, -- items given per farm tick
circleRadius = 5.0, -- default farm zone radius
moneyType = "money", -- "money" | "bank" | "black_money" / "dirty" (normal routes)
drugMoneyType = "black_money", -- money type for drug routes
npcSpawnDistance = 200.0, -- distance to spawn sell NPCs
npcDespawnDistance = 220.0, -- distance to despawn sell NPCs
interactionDistance = 3.0, -- distance to interact with sell NPC
defaultNPCModel = "s_m_m_cntrybar_01",
defaultNPCScenario = "WORLD_HUMAN_SMOKING",
markerType = 1,
farmAnimation = { -- animation played each farm tick
dict = "pickup_object",
clip = "pickup_low",
},
}
-- ================================================================
-- Workstation Defaults
-- ================================================================
Config.workstation = {
enabled = true, -- global toggle; if false, transform points are used instead
defaultInput = 5, -- items consumed per tick
defaultOutput = 1, -- items produced per tick
defaultMaxInput = 3000, -- max items storable
defaultMaxOutput = 300, -- max converted items storable
tickIntervalSeconds = 60, -- how often a workstation tick processes (seconds)
defaultPedModel = "s_m_m_cntrybar_01",
defaultPedAnim = "WORLD_HUMAN_CLIPBOARD",
}
Config.sellAllItemsAtOnce = false -- set to true to sell all items within the cooldown u set, if this is set to false
-- and the cooldown is 10s and it takes 5 items and you have 25, it will take 10 seconds *5 items = 50 seconds. Otherwise you sell all
-- 25 in 5 seconds.
Config.transformAllItemsAtOnce = false -- same as above but for transform points.
Config.transformPoint = {
useOxProgress = true, -- use ox_lib progressBar; set false to use custom, see client/open.lua doProgressBar()
defaultDuration = 5000, -- ms for the progress bar
defaultInputAmount = 10, -- items consumed
defaultOutputAmount = 1, -- items produced
animation = {
dict = "mp_common",
clip = "givetake1_a",
},
}
-- ================================================================
-- Admin Panel Slider Limits
-- These control the min/max ranges for sliders in the admin UI.
-- Adjust to match your server's economy and gameplay balance.
-- ================================================================
Config.adminLimits = {
minPrice = 0,
maxPrice = 2000, -- maximum sell price per item
minFarmTime = 1000, -- minimum farm time (ms) — at least 1 second
maxFarmTime = 60000, -- maximum farm time (ms)
minSellTime = 500, -- minimum sell time (ms)
maxSellTime = 30000, -- maximum sell time (ms)
minFarmAmount = 1, -- minimum items per farm tick
maxFarmAmount = 50, -- maximum items per farm tick
minRadius = 1, -- minimum farm circle radius
maxRadius = 30, -- maximum farm circle radius
minBlipScale = 0.3, -- minimum blip scale
maxBlipScale = 1.5, -- maximum blip scale
minTransformInput = 1, -- minimum transform input amount
maxTransformInput = 100, -- maximum transform input amount
minTransformOutput = 1, -- minimum transform output amount
maxTransformOutput = 100, -- maximum transform output amount
minTransformTime = 1000, -- minimum transform duration (ms)
maxTransformTime = 60000, -- maximum transform duration (ms)
-- Workstation limits
minInputPerTick = 1,
maxInputPerTick = 50,
minOutputPerTick = 1,
maxOutputPerTick = 50,
minMaxInput = 1,
maxMaxInput = 3000,
minMaxOutput = 10,
maxMaxOutput = 500,
minTickSeconds = 1, -- minimum workstation tick interval (seconds)
maxTickSeconds = 600, -- 10 minutes per tick
}
Config.restartBlock = {
enabled = true,
secondsBeforeBlock = 60, -- 1 minute before restart
}
-- ================================================================
-- Farm Boost System
-- ================================================================
Config.farmBoost = {
-- Admin command: /farmboost <percent> (e.g. 10 = +10% items)
-- Set to 0 to disable. Only admins can use this command.
command = "farmboost", -- command name
defaultPercent = 0, -- default boost % on resource start (0 = none)
-- Booster items: items in the player's inventory that grant a temporary
-- farm boost when used. The item is consumed on use and the boost lasts
-- for `durationMinutes`. Multiple booster items stack additively.
boosterItems = {
-- { item = "farm_booster_small", boostPercent = 10, durationMinutes = 15, label = "Small Farm Booster" },
{ item = "farm_booster_large", boostPercent = 50, durationMinutes = 30, label = "Large Farm Booster" },
},
}
-- ================================================================
-- Dynamic Pricing (optional and highly experimental!)
-- If enabled, route prices will fluctuate based on supply/demand:
-- - Each sale lowers the price multiplier by `decayPerSale`
-- - The multiplier recovers over time at `recoveryPerTick`
-- - Multiplier is clamped between `minMultiplier` and `maxMultiplier`
Config.dynamicPrices = {
enabled = false, -- set true to enable supply/demand pricing
checkIntervalMins = 30, -- how often to recalculate multipliers
minMultiplier = 0.5, -- lowest price multiplier
maxMultiplier = 2.0, -- highest price multiplier
decayPerSale = 0.002, -- how much each sale lowers the multiplier
recoveryPerTick = 0.01, -- how much the multiplier recovers per interval
}
-- ================================================================
-- Notification Helper (works on both server and client)
-- Server: Config.Notify(src, msg, title, ntype)
-- Client: Config.Notify(msg, title, ntype) (no src needed)
-- ================================================================
local isServer = IsDuplicityVersion()
Config.Notify = function(srcOrMsg, msgOrTitle, titleOrType, ntype)
if isServer then
-- Server: (src, msg, title, ntype)
local src = srcOrMsg
local msg = tostring(msgOrTitle or "")
local title = tostring(titleOrType or "Drug Routes")
local t = ntype or "inform"
if GetResourceState("ox_lib") == "started" then
TriggerClientEvent("ox_lib:notify", src, {
title = title,
description = msg,
type = t,
position = "bottom-right",
})
else
TriggerClientEvent("chat:addMessage", src, {
args = { ("^3%s^7"):format(title), msg }
})
end
else
-- Client: (msg, title, ntype) — no src
local msg = tostring(srcOrMsg or "")
local title = tostring(msgOrTitle or "Drug Routes")
local t = titleOrType or "inform"
if GetResourceState("ox_lib") == "started" then
exports.ox_lib:notify({
title = title,
description = msg,
type = t,
position = "bottom-right",
})
else
TriggerEvent("chat:addMessage", {
args = { ("^3%s^7"):format(title), msg }
})
end
end
end
Video Previewhttps://www.youtube.com/watch?v=1TkSSjR_0v4
Images of the Product
Purchasehttps://alva-scripts.com/scripts/7317153 (alva-scripts.com)
Support / UpdatesSupport + lifetime updates are available via my Discord.
(Linked on the store page) (alva-scripts.com)
The first 5 people to create a ticket on my discord will receive this product completly for free!
Other Products you might enjoy| Code is accessible | No (Protected with FiveM Asset Escrow), only Configs are |
| Subscription-based | No |
| Lines of Code | ~5000 |
| Framework | ESX / QBCore (auto-detect) |
| Requirements | MySQL (oxmysql) |
| Optional | ox_target, ox_lib |
| Support | Yes |
See what others are saying about this script.
Share your experience and help others.