Requirements
| Resource | Required | Notes |
|---|---|---|
| ox_lib | Yes | Text UI, progress bars and notifications, must start first |
| OneSync | Yes | Robodogs, cameras, barriers and the voice effects run on state bags |
| Framework | Yes | qb-core, qbx_core or es_extended, detected automatically |
| Inventory | Yes | ox_inventory, qs-inventory, qb-inventory, ps-inventory, lj-inventory or codem-inventory, detected automatically |
| Voice | No | pma-voice, mumble-voip or saltychat for the megaphone and the mouth tape, native Mumble is used otherwise |
| Target | No | ox_target, qb-target or interact, a text UI prompt is used otherwise |
| Doorlock | No | Detected automatically for the battering ram, see Config Settings |
Step 1 - Add the resource#
Drag the frkn-tacticalpack folder into your resources directory, for example:
resources/[qb]/frkn-tacticalpack
Step 2 - Start the resource#
Add this to your server.cfg, after ox_lib, your framework, your inventory and your voice resource:
ensure frkn-tacticalpack
If your resources are grouped with ensure [qb] or a similar folder start, make sure frkn-tacticalpack is inside that group or started after it.
Step 3 - Enable native audio#
The megaphone tone is an audio submix that only works with native audio. Add this to your server.cfg:
setr voice_useNativeAudio true
Without this convar the megaphone still makes your voice carry further, but the megaphone sound is never applied and no error is shown.
Step 4 - Add the items#
Every tool is one item. Its texture comes from the job of the player using it, so there are no separate police / sheriff / FBI items.
Paste into qb-core/shared/items.lua:
frkn_ram = { name = 'frkn_ram', label = 'Battering Ram', weight = 1000, type = 'item', image = 'frkn_ram.png', unique = false, useable = true, shouldClose = true, description = 'Breaks open locked doors. Walk up to a door and left click; the ram swings and the door opens.' },
frkn_nvg = { name = 'frkn_nvg', label = 'Night Vision Goggles', weight = 300, type = 'item', image = 'frkn_nvg.png', unique = false, useable = true, shouldClose = true, description = 'Night vision helmet. N switches night / thermal vision, E marks the spot you look at, H clears the marks.' },
frkn_throwcam = { name = 'frkn_throwcam', label = 'Tactical Throwable Camera', weight = 400, type = 'item', image = 'frkn_throwcam.png', unique = false, useable = true, shouldClose = true, description = 'Throwable camera. Hold and release left click to throw it, then watch and drive it from the feed.' },
frkn_robodog = { name = 'frkn_robodog', label = 'Robodog', weight = 1500, type = 'item', image = 'frkn_robodog.png', unique = false, useable = true, shouldClose = true, description = 'Remote controlled robot dog. Deploy it, drive it with W A S D and stop suspects with its taser.' },
frkn_mouthtape = { name = 'frkn_mouthtape', label = 'Mouth Tape', weight = 50, type = 'item', image = 'frkn_mouthtape.png', unique = false, useable = true, shouldClose = true, description = 'Tapes the mouth of the person next to you; a taped person cannot talk.' },
frkn_flashbang = { name = 'frkn_flashbang', label = 'Flashbang', weight = 300, type = 'item', image = 'frkn_flashbang.png', unique = false, useable = true, shouldClose = true, description = 'Stun grenade. Right click aims, left click throws; anyone looking at the bang is blinded and deafened for a while.' },
frkn_pepperspray = { name = 'frkn_pepperspray', label = 'Pepper Spray', weight = 200, type = 'item', image = 'frkn_pepperspray.png', unique = false, useable = true, shouldClose = true, description = 'Pepper spray. Hold left click to spray; the target sees blurry and slows down.' },
frkn_megaphone = { name = 'frkn_megaphone', label = 'Megaphone', weight = 300, type = 'item', image = 'frkn_megaphone.png', unique = false, useable = true, shouldClose = true, description = 'Handheld megaphone. Your voice carries much further while you talk.' },
frkn_bolawrap = { name = 'frkn_bolawrap', label = 'BolaWrap', weight = 500, type = 'item', image = 'frkn_bolawrap.png', unique = false, useable = true, shouldClose = true, description = 'Fires a restraint cord from a distance. Aim and fire; the cord wraps around the arms or legs of the suspect.' },
frkn_mobilespike = { name = 'frkn_mobilespike', label = 'Mobile Spike Strip', weight = 1000, type = 'item', image = 'frkn_mobilespike.png', unique = false, useable = true, shouldClose = true, description = 'Spike strip mounted on a vehicle. Deploy it with a key while driving to burst the tyres of the car you chase.' },
frkn_clamp = { name = 'frkn_clamp', label = 'Wheel Clamp', weight = 800, type = 'item', image = 'frkn_clamp.png', unique = false, useable = true, shouldClose = true, description = 'Wheel clamp. A clamped vehicle cannot move.' },
frkn_clamp_heavy = { name = 'frkn_clamp_heavy', label = 'Heavy Wheel Clamp', weight = 1000, type = 'item', image = 'frkn_clamp_heavy.png', unique = false, useable = true, shouldClose = true, description = 'Heavy wheel clamp. It cannot be lockpicked and the clamped vehicle cannot move.' },
frkn_grappler = { name = 'frkn_grappler', label = 'Police Grappler', weight = 1000, type = 'item', image = 'frkn_grappler.png', unique = false, useable = true, shouldClose = true, description = 'Net mounted on the front bumper. It wraps around a rear tyre of a fleeing car and stops it.' },
frkn_roadcontrol = { name = 'frkn_roadcontrol', label = 'Road Control Device', weight = 800, type = 'item', image = 'frkn_roadcontrol.png', unique = false, useable = true, shouldClose = true, description = 'Road control device. Using it opens the placement menu; CAPS LOCK switches between bollard, cone, work barrier, police barrier, arrow barrier and road plate. Never used up, placed items are not taken from your inventory.' },
frkn_deployshield = { name = 'frkn_deployshield', label = 'Deployable Shield', weight = 2500, type = 'item', image = 'frkn_deployshield.png', unique = false, useable = true, shouldClose = true, description = 'Deployable shield. Use it to set a curved shield down in front of you; it extends up out of its base and stops bullets. Next to it, G lowers or raises it and E picks it back up.' },
frkn_radar = { name = 'frkn_radar', label = 'Speed Radar', weight = 300, type = 'item', image = 'frkn_radar.png', unique = false, useable = true, shouldClose = true, description = 'Handheld speed radar. Aim at a vehicle to see its speed on the display.' },
frkn_chaincuffs = { name = 'frkn_chaincuffs', label = 'Chain Cuffs', weight = 300, type = 'item', image = 'frkn_chaincuffs.png', unique = false, useable = true, shouldClose = true, description = 'Chain handcuffs. Chain a suspect to yourself, to another person or to an object.' },
frkn_chainkey = { name = 'frkn_chainkey', label = 'Chain Cuffs Key', weight = 50, type = 'item', image = 'frkn_chainkey.png', unique = true, useable = true, shouldClose = true, description = 'Key for chain handcuffs. Use it next to the chain to unlock it.' },
frkn_shield = { name = 'frkn_shield', label = 'Ballistic Shield', weight = 1000, type = 'item', image = 'frkn_shield.png', unique = false, useable = true, shouldClose = true, description = 'Ballistic shield. Stops bullets from the front, a pistol can be used behind it.' },
frkn_kit_traffic = { name = 'frkn_kit_traffic', label = 'Traffic Kit', weight = 500, type = 'item', image = 'frkn_kit_traffic.png', unique = false, useable = true, shouldClose = true, description = 'Ready bag for the traffic unit. Contents: 1x Speed Radar, 1x Road Control Device, 2x Wheel Clamp, 1x Heavy Wheel Clamp, 1x Mobile Spike Strip, 1x Police Grappler' },
frkn_kit_assault = { name = 'frkn_kit_assault', label = 'Assault Kit', weight = 500, type = 'item', image = 'frkn_kit_assault.png', unique = false, useable = true, shouldClose = true, description = 'Ready bag for the raid team. Contents: 1x Battering Ram, 1x Ballistic Shield, 1x Deployable Shield, 3x Flashbang, 1x Night Vision Goggles, 1x Tactical Throwable Camera' },
frkn_kit_support = { name = 'frkn_kit_support', label = 'Support Kit', weight = 500, type = 'item', image = 'frkn_kit_support.png', unique = false, useable = true, shouldClose = true, description = 'Ready bag for the support unit. Contents: 1x Robodog, 1x Megaphone' },
frkn_kit_restraint = { name = 'frkn_kit_restraint', label = 'Restraint Kit', weight = 500, type = 'item', image = 'frkn_kit_restraint.png', unique = false, useable = true, shouldClose = true, description = 'Ready bag for restraint and arrests. Contents: 1x BolaWrap, 2x Chain Cuffs, 3x Mouth Tape, 1x Pepper Spray' },
Paste into the return { ... } table in ox_inventory/data/items.lua:
['frkn_ram'] = {
label = 'Battering Ram',
description = 'Breaks open locked doors. Walk up to a door and left click; the ram swings and the door opens.',
weight = 1000,
stack = true,
close = true,
client = { export = 'frkn-tacticalpack.useRam' },
},
['frkn_nvg'] = {
label = 'Night Vision Goggles',
description = 'Night vision helmet. N switches night / thermal vision, E marks the spot you look at, H clears the marks.',
weight = 300,
stack = true,
close = true,
client = { export = 'frkn-tacticalpack.useNvg' },
},
['frkn_throwcam'] = {
label = 'Tactical Throwable Camera',
description = 'Throwable camera. Hold and release left click to throw it, then watch and drive it from the feed.',
weight = 400,
stack = true,
close = true,
client = { export = 'frkn-tacticalpack.useThrowCam' },
},
['frkn_robodog'] = {
label = 'Robodog',
description = 'Remote controlled robot dog. Deploy it, drive it with W A S D and stop suspects with its taser.',
weight = 1500,
stack = true,
close = true,
client = { export = 'frkn-tacticalpack.useRobodog' },
},
['frkn_mouthtape'] = {
label = 'Mouth Tape',
description = 'Tapes the mouth of the person next to you; a taped person cannot talk.',
weight = 50,
stack = true,
close = true,
client = { export = 'frkn-tacticalpack.useMouthTape' },
},
['frkn_flashbang'] = {
label = 'Flashbang',
description = 'Stun grenade. Right click aims, left click throws; anyone looking at the bang is blinded and deafened for a while.',
weight = 300,
stack = true,
close = true,
client = { export = 'frkn-tacticalpack.useFlashbang' },
},
['frkn_pepperspray'] = {
label = 'Pepper Spray',
description = 'Pepper spray. Hold left click to spray; the target sees blurry and slows down.',
weight = 200,
stack = true,
close = true,
client = { export = 'frkn-tacticalpack.usePepperSpray' },
},
['frkn_megaphone'] = {
label = 'Megaphone',
description = 'Handheld megaphone. Your voice carries much further while you talk.',
weight = 300,
stack = true,
close = true,
client = { export = 'frkn-tacticalpack.useMegaphone' },
},
['frkn_bolawrap'] = {
label = 'BolaWrap',
description = 'Fires a restraint cord from a distance. Aim and fire; the cord wraps around the arms or legs of the suspect.',
weight = 500,
stack = true,
close = true,
client = { export = 'frkn-tacticalpack.useBolawrap' },
},
['frkn_mobilespike'] = {
label = 'Mobile Spike Strip',
description = 'Spike strip mounted on a vehicle. Deploy it with a key while driving to burst the tyres of the car you chase.',
weight = 1000,
stack = true,
close = true,
client = { export = 'frkn-tacticalpack.useMobileSpike' },
},
['frkn_clamp'] = {
label = 'Wheel Clamp',
description = 'Wheel clamp. A clamped vehicle cannot move.',
weight = 800,
stack = true,
close = true,
client = { export = 'frkn-tacticalpack.useClamp' },
},
['frkn_clamp_heavy'] = {
label = 'Heavy Wheel Clamp',
description = 'Heavy wheel clamp. It cannot be lockpicked and the clamped vehicle cannot move.',
weight = 1000,
stack = true,
close = true,
client = { export = 'frkn-tacticalpack.useClampHeavy' },
},
['frkn_grappler'] = {
label = 'Police Grappler',
description = 'Net mounted on the front bumper. It wraps around a rear tyre of a fleeing car and stops it.',
weight = 1000,
stack = true,
close = true,
client = { export = 'frkn-tacticalpack.useGrappler' },
},
['frkn_roadcontrol'] = {
label = 'Road Control Device',
description = 'Road control device. Using it opens the placement menu; CAPS LOCK switches between bollard, cone, work barrier, police barrier, arrow barrier and road plate. Never used up, placed items are not taken from your inventory.',
weight = 800,
stack = true,
close = true,
client = { export = 'frkn-tacticalpack.useRoadControl' },
},
['frkn_deployshield'] = {
label = 'Deployable Shield',
description = 'Deployable shield. Use it to set a curved shield down in front of you; it extends up out of its base and stops bullets. Next to it, G lowers or raises it and E picks it back up.',
weight = 2500,
stack = true,
close = true,
client = { export = 'frkn-tacticalpack.useDeployShield' },
},
['frkn_radar'] = {
label = 'Speed Radar',
description = 'Handheld speed radar. Aim at a vehicle to see its speed on the display.',
weight = 300,
stack = true,
close = true,
client = { export = 'frkn-tacticalpack.useRadar' },
},
['frkn_chaincuffs'] = {
label = 'Chain Cuffs',
description = 'Chain handcuffs. Chain a suspect to yourself, to another person or to an object.',
weight = 300,
stack = true,
close = true,
client = { export = 'frkn-tacticalpack.useChainCuffs' },
},
['frkn_chainkey'] = {
label = 'Chain Cuffs Key',
description = 'Key for chain handcuffs. Use it next to the chain to unlock it.',
weight = 50,
stack = false,
close = true,
client = { export = 'frkn-tacticalpack.useChainKey' },
},
['frkn_shield'] = {
label = 'Ballistic Shield',
description = 'Ballistic shield. Stops bullets from the front, a pistol can be used behind it.',
weight = 1000,
stack = true,
close = true,
client = { export = 'frkn-tacticalpack.useShield' },
},
['frkn_kit_traffic'] = {
label = 'Traffic Kit',
weight = 500,
stack = true,
close = true,
description = 'Ready bag for the traffic unit. Contents: 1x Speed Radar, 1x Road Control Device, 2x Wheel Clamp, 1x Heavy Wheel Clamp, 1x Mobile Spike Strip, 1x Police Grappler',
client = { export = 'frkn-tacticalpack.useKit' },
},
['frkn_kit_assault'] = {
label = 'Assault Kit',
weight = 500,
stack = true,
close = true,
description = 'Ready bag for the raid team. Contents: 1x Battering Ram, 1x Ballistic Shield, 1x Deployable Shield, 3x Flashbang, 1x Night Vision Goggles, 1x Tactical Throwable Camera',
client = { export = 'frkn-tacticalpack.useKit' },
},
['frkn_kit_support'] = {
label = 'Support Kit',
weight = 500,
stack = true,
close = true,
description = 'Ready bag for the support unit. Contents: 1x Robodog, 1x Megaphone',
client = { export = 'frkn-tacticalpack.useKit' },
},
['frkn_kit_restraint'] = {
label = 'Restraint Kit',
weight = 500,
stack = true,
close = true,
description = 'Ready bag for restraint and arrests. Contents: 1x BolaWrap, 2x Chain Cuffs, 3x Mouth Tape, 1x Pepper Spray',
client = { export = 'frkn-tacticalpack.useKit' },
},
Do not add consume, client.usetime, client.status, client.event or server.export to these items. ox_inventory would remove the item on its own and the script would never run. The script decides when an item is used up.
Make sure ensure ox_inventory comes before ensure frkn-tacticalpack. Every item except the chain cuffs key stacks; the pepper spray keeps its charge in metadata, so cans with a different charge stay in separate slots.
Item names must match the name of each line in Items (and the item of each kit in Kits) in shared/config.lua. If you rename an item, rename it in both places.
Step 5 - Copy the item images#
Copy every image from frkn-tacticalpack/itemimages/ into your inventory's image folder:
| Inventory | Folder |
|---|---|
| qb-inventory | qb-inventory/html/images/ |
| ps-inventory / lj-inventory | html/images/ inside the inventory |
| ox_inventory | ox_inventory/web/images/ |
| qs-inventory | qs-inventory/html/images/ |
| codem-inventory | codem-inventory/html/itemimages/ |
The images/ folder in the resource belongs to the script itself (night vision overlay, map marks). Do not copy it to your inventory.
Step 6 - Give yourself admin access#
Admin commands use AdminPermission in shared/config.lua:
AdminPermission = "admin",
| Framework | How it is checked |
|---|---|
| QBCore / Qbox | QBCore.Functions.HasPermission(source, AdminPermission) |
| ESX | The player's group equals AdminPermission (or is superadmin) |
The server console can always run every admin command.
Step 7 - Set your language#
Language = "en",
Available: en, tr, de, fr, es, pt, it, ru, pl, nl, ar. Every text players see comes from locales/, including notifications, prompts, the NUI screens, the radar's LCD and Discord webhook messages.
Commands#
| Command | Who | Description |
|---|---|---|
/tacpurge | Admin | Removes every camera and robodog and deletes every pack prop left in the world, e.g. after a crash |
/unclamp [plate] | Admin | Removes every clamp, or the clamps on one plate (also on vehicles that are not spawned) |
/ungrapple | Admin | Releases every grappler tether |
/unbola <id> | Admin | Frees a player from the BolaWrap |
/unchain [id] | Admin | Removes one player's chain, or every chain |
/untape <id> | Admin | Removes the mouth tape from a player |
/bollardclear | Admin | Picks up every road barrier |
/bollardclear mine | Everyone | Picks up your own road barriers |
/tacblockerclear | Admin | Picks up every road blocker plate |
Troubleshooting#
| Problem | Fix |
|---|---|
| Using an item does nothing | The item name in your inventory must match the name of that item in Items in shared/config.lua. On ox_inventory, remove consume / server.export from the item |
| "You do not have the required job" | Add the job to JobRestriction.jobs with a grade and a theme, see Config Settings |
| "This equipment is disabled on the server" | The item's line in Items (or the kit in Kits) has enabled = false |
| Megaphone only makes the voice louder | Add setr voice_useNativeAudio true (Step 3) and restart the server |
| Item images are missing | Copy itemimages/ into your inventory's image folder (Step 5) |
| The robodog or camera disappears and the item comes back | It went past maxRange (80 m by default) from the player using it. Raise Robodog.maxRange / ThrowCam.maxRange or set it to 0 |
| "That is more bollards than you are allowed to have out" | Every road control prop counts towards Bollard.maxPerPlayer (6 by default). Pick some up or raise the limit |
| The ram does not open a door | Check system and onlyLocked in Ram.DoorLock. Doors your doorlock does not know are rammed through nativeFallback (on by default, see Advanced settings) |
| Props are invisible after an update | Restart the whole server and reconnect; FiveM caches streamed models by name |