π« Weapon Customization β
VORP
Lay your gun on the gunsmith counter and work on it: parts, metals, engravings and tints, chosen on a live top-down view of the real weapon and kept per serial number.
Features β
- The real counter experience. The player lays the weapon down with the game's own gunsmith animation and picks it back up the same way, over a live top-down view of the actual weapon.
- 30 weapons catalogued. Pistols, revolvers, repeaters, rifles, shotguns, bows and the hunting knife: the set the game itself customizes, each with its own parts, poses and close-up angles.
- Parts, metals, engravings and tints. Every piece is priced in an open prices file (765 rows). A piece can cost cash, gold, or both. The till charges only what the visit adds, and takes nothing unless the player can cover the whole order.
- Saved per serial number. Every weapon keeps its own look, and it follows the gun through a stash, a trade or a drop. Storage is automatic, there is no SQL file to run.
- The room watches the bench. Players nearby see the weapon on the counter and every part fitted to it, live, as the smith works.
- Walk up and watch. A second prompt at a counter in use gives you the smith's own view of the bench. No menu, no prompt, and the camera does not move. Watching is not work, so the job lists do not gate it: anyone may stand and look.
- One smith at a bench. A counter already in use turns the next player away instead of opening a second view over the same gun stand.
- Job-gated shops. Each city lists the jobs allowed to use its counter, and job changes reach the player instantly.
Config.CanUsereplaces the whole gate with a rule of your own, checked on the server. - A counter can specialise. Give a shop a
weaponslist and it works on those and nothing else: a knife bench, a rifle bench, a bow bench. - A Discord log of every order. Who ordered and as which character, what was paid, the weapon and its serial, whether it is that gun's first time at the counter, and every part changed, old piece to new with its price.
- Push to talk at the counter. Voice keeps working while the menu is open (
Config.talkinmenu). - The order ring takes you there. Click a piece in the ring and the menu opens on that option's row.
- The gunsmith's own sounds. Browsing left and right, the till on a purchase, gold being spent, a locked counter, an order the player cannot cover.
- 5 languages. English, Arabic, French, Spanish, German. A missing line falls back to English, never to a blank label.
- In-place setup tool.
/setupshoplays a weapon on any counter you stand at, lets you frame it on screen, and hands you a ready-to-pasteConfig.Locationsblock. - Nothing runs when nothing is happening. No tick and no per-frame work once a gun wears its look.
resmonreads 0.00 ms at rest. - A built-in version checker prints update notices in the server console.
Requirements β
| Dependency | Used for |
|---|---|
vorp_core | character, money and job data |
oxmysql | storage |
Installation β
Drop
zoo_weaponcustomizationinto your resources.Add it to your
server.cfg, after the dependencies:iniensure vorp_core ensure oxmysql ensure zoo_weaponcustomizationStart the server. The database table is created automatically, there is no SQL file to run.
Set
Config.inventoryto match your inventory: see Notes for VORP servers.
Configuration β
Everything below lives in config/config.lua. Prices are in config/prices.lua, one row per piece with cash and gold columns. Config, prices and every locale file are open to edit.
| Option | Default | What it does |
|---|---|---|
Config.locale | 'en' | menu language: en, ar, fr, es, de |
Config.Debug | false | opens the /setupshop setup tool, and prints players' script errors in the server console |
Config.promptkey | 0x760A9C6F (G) | key that opens the counter |
Config.prompttext | 'Show weapon' | what the prompt reads |
Config.promptrange | 3.0 | how close the prompt shows, in metres |
Config.exitkey | 0x156F7119 (Backspace) | key that closes the menu |
Config.talkinmenu | true | push to talk works while the menu is open |
Config.showserial | true | show the serial under the weapon name |
Config.watchers | true | players nearby see the gun on the bench |
Config.watcherrange | 25.0 | how far the bench can be seen, in metres |
Config.watchercam | true | let anyone watch a counter in use |
Config.watchkey | 0xCEFD9220 (E) | key that starts watching |
Config.watchtext | 'Watch' | what the watch prompt reads |
Config.blipsprite | gunsmith icon | map blip sprite |
Config.bliplabel | 'Weapon Customization' | map blip name; a shop can override it |
Config.jobonly | true | only the jobs each shop lists may work |
Config.jobrank | 0 | lowest job grade served |
Config.CanUse | not set | your own server-side rule for who may work |
Config.Locations | 5 cities | the shops: stand, counter, jobs, weapons |
Discord log β
Set in config/config.lua. An order that changes nothing is not posted.
| Option | Default | What it does |
|---|---|---|
Config.Webhook.Enabled | false | post every order to Discord |
Config.Webhook.Url | '' | the channel's webhook address |
Config.Webhook.Name | 'Gunsmith' | the name the messages are posted under |
Config.Webhook.Color | 13938487 | the colour of the message's side bar |
Adding a shop β
Set Config.Debug = true, restart, stand where the smith should stand and type /setupshop with a weapon in hand. Frame the gun with the on-screen panel, press Copy, and paste the block into Config.Locations. Turn Config.Debug back off when you are done.
A shop entry takes an optional weapons list. With one, that counter works on those weapons only, on the client and on the server both.
{ name = 'Valentine',
blip = true,
jobs = { 'gunsmith' },
stand = { x = -277.05, y = 778.75, z = 119.50, h = 275.00 },
counter = { x = -276.175, y = 778.730, z = 119.550 },
weapons = { 'WEAPON_MELEE_KNIFE' }, -- leave out to take everything
},And an optional rule of your own, in place of the job lists:
Config.CanUse = function(source, shop)
return exports['my_tribes']:IsInTribe(source, 'wapiti')
endNotes for VORP servers β
Set Config.inventory to match your inventory β
Use 'v2' for the rewritten vorp_inventory-v2, and 'v1' for 4.5 and older. Its version line is in vorp_inventory/fxmanifest.lua. Set wrong, weapons come out of the satchel bare or a pair of one model shares a look. The console says which inventory it found at start, and warns in red when the setting does not match.
The inventory is not named in dependencies on purpose: it ships under two folder names and a dependency can only name one. Nothing here calls it directly.
vorp_weaponsv2: one handler in it has to go β
As it ships, the two cannot both run. Its server listens for syn_weapons:weaponused, the event vorp_inventory fires on every equip, and applies that weapon's saved parts to the ped. A ped registration is by weapon model, so it lands on every gun of that model and on top of what is fitted here, and a gun wearing both comes out visibly wrong: measured on the bench, a pair of revolvers with the barrel mangled. Its registration cannot simply be undone either, because clearing one strips the gun on the next rebuild rather than restoring anything.
But it is also VORP's ammo system, which is why removing it is the wrong answer: its server registers all 55 ammo items out of its own config/ammo.lua, and vorp_inventory registers none of them itself. Take it out and ammo boxes do nothing on a double click, and ammo never runs out.
So delete the syn_weapons:weaponused handler from its server/server.lua and keep everything else. Nothing else sends vorp_weapons:givecomp and nothing else listens for syn_weapons:weaponused, so that one handler is the whole path. The ammo registration is further down the same file and is not touched. Measured on the bench: with it gone, looks fitted here survive an equip, and its ammo, crafting and station all still work.
The console says at start whether vorp_weaponsv2 is running with that handler removed, and warns in red when it is the original.
Its station stands where this one does β
Both put a counter at the gunsmith, which is one place in the game: measured, 0.24 m apart in Valentine and 0.80 m in Rhodes, well inside Config.promptrange, so a player standing there is offered both prompts at once. Empty customizationLocations and craftinglocation in its config. Each table is read in exactly one place, the loop that draws that prompt, so an empty one draws nothing and the rest of the script is untouched. To keep its station instead, move its coordinates somewhere else entirely rather than leaving them on top of these.
Prices in gold β
The gold price column charges the gold account. Every bundled price uses cash only.
