Inicio › Documentación › Objetos · origen_ilegalv2
origen_ilegalv2 requiere que se registren 18 objetos únicos en tu inventario para que el recurso funcione correctamente. Copia el bloque que corresponda a tu sistema de inventario y pégalo en el fichero adecuado.
empty_weed_bag es compartido entre el laboratorio de meta y el de coca. Regístralo una sola vez.
Los items graffiti_spray y graffiti_eraser solo son necesarios cuando Config.Graffiti.Enable = true.
| Objeto | Laboratorio | Función | Utilizable |
|---|---|---|---|
ephedrine |
Meta | Ingrediente de cocinado | No |
acetone |
Meta | Ingrediente de cocinado | No |
empty_weed_bag |
Meta / Coca | Ingrediente de embolsado (compartido) | No |
methbags |
Meta | Producto final | Venta de drogas |
coca_leaf |
Coca | Ingrediente de procesado | No |
coke |
Coca | Intermedio (salida de make_powder, entrada de cut_coke) | No |
bakingsoda |
Coca | Ingrediente de corte | No |
loosecoke |
Coca | Intermedio (salida de cut_coke, entrada de bag_coke) | No |
cokebaggy |
Coca | Producto final | Venta de drogas |
wetcannabis |
Marihuana | Resultado de la cosecha · ingrediente de secado | No |
drycannabis |
Marihuana | Resultado del secado · ingrediente de molido | No |
weedgrinder |
Marihuana | Herramienta obligatoria — no se consume | No |
grindedweed |
Marihuana | Resultado del molido · ingrediente de embolsado | No |
bluntwrap |
Marihuana | Ingrediente de embolsado | No |
blunt |
Marihuana | Producto final | Venta de drogas |
ilegal_cad |
Banda | Credencial del panel de banda — no se consume al usarse | Sí |
graffiti_spray |
Grafiti | Lata de spray — se consume al colocar un tag | Sí |
graffiti_eraser |
Grafiti | Trapo de limpieza — se consume al borrar un grafiti | Sí |
Los objetos marcados como Sí abren un menú o inician una acción cuando el jugador los usa. En ox_inventory necesitan la configuración adicional descrita en Objetos utilizables en ox_inventory.
Los objetos marcados como Venta de drogas solo pasan a ser utilizables cuando figuran en Config.DrugSales.DrugList.
Añade las siguientes entradas a ox_inventory/data/items.lua:
En ox_inventory el icono debe declararse dentro de la tabla client como client = { image = '...' }. Un campo image de nivel superior lo ignora el inventario y el objeto recurrirá a <item_name>.png.
-- ── METH LAB ──────────────────────────────────────────────────────────────────
['ephedrine'] = {
label = 'Ephedrine',
weight = 100,
stack = true,
close = true,
description = 'Chemical precursor for methamphetamine production.',
client = { image = 'ephedrine.png' },
},
['acetone'] = {
label = 'Acetone',
weight = 200,
stack = true,
close = true,
description = 'Chemical solvent. Required for the cooking process.',
client = { image = 'acetone.png' },
},
['empty_weed_bag'] = {
label = 'Empty Bag',
weight = 10,
stack = true,
close = true,
description = 'Empty plastic bag. Used for packaging products.',
client = { image = 'empty_weed_bag.png' },
},
['methbags'] = {
label = 'Meth Bags',
weight = 150,
stack = true,
close = true,
description = 'Crystallized methamphetamine ready for distribution.',
client = { image = 'methbags.png' },
},
-- ── COKE LAB ──────────────────────────────────────────────────────────────────
['coca_leaf'] = {
label = 'Coca Leaf',
weight = 50,
stack = true,
close = true,
description = 'Raw coca leaf. Primary raw material for processing.',
client = { image = 'coca_leaf.png' },
},
['coke'] = {
label = 'Base Powder',
weight = 80,
stack = true,
close = true,
description = 'Unprocessed cocaine powder. Intermediate product.',
client = { image = 'coke.png' },
},
['bakingsoda'] = {
label = 'Baking Soda',
weight = 50,
stack = true,
close = true,
description = 'Sodium bicarbonate. Cutting agent for cocaine.',
client = { image = 'bakingsoda.png' },
},
['loosecoke'] = {
label = 'Cut Cocaine',
weight = 80,
stack = true,
close = true,
description = 'Cut cocaine ready for bagging.',
client = { image = 'loosecoke.png' },
},
['cokebaggy'] = {
label = 'Cocaine Baggy',
weight = 100,
stack = true,
close = true,
description = 'Bagged cocaine ready for distribution.',
client = { image = 'cokebaggy.png' },
},
-- ── WEED LAB ──────────────────────────────────────────────────────────────────
['wetcannabis'] = {
label = 'Wet Cannabis',
weight = 100,
stack = true,
close = true,
description = 'Freshly harvested cannabis flower. Must be dried.',
client = { image = 'wetcannabis.png' },
},
['drycannabis'] = {
label = 'Dry Cannabis',
weight = 60,
stack = true,
close = true,
description = 'Dried cannabis ready for grinding.',
client = { image = 'drycannabis.png' },
},
['weedgrinder'] = {
label = 'Grinder',
weight = 200,
stack = false,
close = true,
description = 'Herb grinder. Not consumed on use.',
client = { image = 'weedgrinder.png' },
},
['grindedweed'] = {
label = 'Ground Cannabis',
weight = 40,
stack = true,
close = true,
description = 'Ground cannabis ready for bagging.',
client = { image = 'grindedweed.png' },
},
['bluntwrap'] = {
label = 'Blunt Wrap',
weight = 10,
stack = true,
close = true,
description = 'Rolling paper for blunts.',
client = { image = 'bluntwrap.png' },
},
['blunt'] = {
label = 'Blunt',
weight = 30,
stack = true,
close = true,
description = 'Rolled blunt ready for sale.',
client = { image = 'blunt.png' },
},
-- ── GANG CAD ──────────────────────────────────────────────────────────────────
['ilegal_cad'] = {
label = 'Gang CAD',
weight = 0,
stack = true,
close = false,
consume = 0,
description = 'Gang panel access credential. Not consumed on use.',
client = { image = 'ilegal_cad.png' },
server = { export = 'origen_ilegalv2.ilegal_cad' },
},
-- ── GRAFFITI ──────────────────────────────────────────────────────────────────
['graffiti_spray'] = {
label = 'Spray Can',
weight = 300,
stack = true,
close = true,
consume = 0,
description = 'Aerosol spray can. Used to tag gang graffiti. Consumed on placement.',
client = { image = 'graffiti_spray.png' },
server = { export = 'origen_ilegalv2.graffiti_spray' },
},
['graffiti_eraser'] = {
label = 'Cleaning Rag',
weight = 100,
stack = true,
close = true,
consume = 0,
description = 'Solvent-soaked rag. Used to clean graffiti tags. Consumed on use.',
client = { image = 'graffiti_eraser.png' },
server = { export = 'origen_ilegalv2.graffiti_eraser' },
},ox_inventory no lee el registro del framework que usan QBCore.Functions.CreateUseableItem o ESX.RegisterUsableItem cuando un objeto declara su propio handler. Para que los objetos utilizables de este recurso funcionen de forma nativa en ox_inventory, hacen falta dos piezas.
Los tres objetos utilizables de arriba ya lo incluyen:
consume = 0,
server = { export = 'origen_ilegalv2.<item_name>' },consume = 0 es obligatorio. Al declarar server.export, ox_inventory establece consume = 1 automáticamente, lo que elimina el objeto del inventario del jugador en cada uso. Eso quitaría el CAD de banda (una credencial permanente) y consumiría los objetos de grafiti dos veces, porque el recurso ya los elimina por sí mismo tras una acción exitosa.
Usa el número 0, no false ni nil. En Lua 0 es verdadero, así que es el único valor que a la vez evita el consumo automático y sigue activando el handler del objeto.
Crea custom/server/ox_usable_exports.lua dentro del recurso. El patrón custom/server/*.lua ya está declarado en fxmanifest.lua, así que no hace falta cambiar el manifest, y la carpeta figura en escrow_ignore, por lo que el fichero sobrevive a las actualizaciones del recurso.
if GetResourceState('ox_inventory') ~= 'started' then return end
local bound = {}
local function buildItemData(item, inventory, slot)
local slotData = slot and inventory.items and inventory.items[slot]
return {
name = item and item.name,
label = item and item.label,
slot = slot,
count = slotData and slotData.count or 1,
metadata = slotData and slotData.metadata or {},
}
end
local function bindOxUsable(itemName, cb)
if not itemName or bound[itemName] then return end
bound[itemName] = true
exports(itemName, function(event, item, inventory, slot)
if event ~= 'usingItem' then return end
if not inventory or not inventory.player then return end
cb(inventory.id, buildItemData(item, inventory, slot))
end)
end
local baseRegister = Framework and Framework.RegisterUsableItem
if not baseRegister then
print('^1[origen_ilegalv2] Framework.RegisterUsableItem not available - ox_inventory exports not mounted^0')
return
end
Framework.RegisterUsableItem = function(itemName, cb)
baseRegister(itemName, cb)
bindOxUsable(itemName, cb)
endEl fichero envuelve Framework.RegisterUsableItem, de modo que todos los objetos que registra el recurso obtienen automáticamente su export de ox_inventory. Esto cubre también las drogas creadas en tiempo de ejecución desde el panel de administración.
El registro original del framework se conserva como alternativa. No hay doble ejecución: ox_inventory solo recurre al registro del framework cuando el objeto no declara consume, y estos objetos sí lo declaran.
ox_inventory no puede crear objetos en tiempo de ejecución. Una droga añadida desde el panel de administración obtiene su handler de uso, pero el objeto en sí debe añadirse manualmente a ox_inventory/data/items.lua, seguido de un reinicio del recurso.
Añade las siguientes entradas a qb-core/shared/items.lua:
-- ── METH LAB ──────────────────────────────────────────────────────────────────
['ephedrine'] = { name = 'ephedrine', label = 'Ephedrine', weight = 100, type = 'item', image = 'ephedrine.png', unique = false, useable = false, shouldClose = true, combinable = nil, description = 'Chemical precursor for methamphetamine production.' },
['acetone'] = { name = 'acetone', label = 'Acetone', weight = 200, type = 'item', image = 'acetone.png', unique = false, useable = false, shouldClose = true, combinable = nil, description = 'Chemical solvent. Required for the cooking process.' },
['empty_weed_bag'] = { name = 'empty_weed_bag', label = 'Empty Bag', weight = 10, type = 'item', image = 'empty_weed_bag.png', unique = false, useable = false, shouldClose = true, combinable = nil, description = 'Empty plastic bag. Used for packaging products.' },
['methbags'] = { name = 'methbags', label = 'Meth Bags', weight = 150, type = 'item', image = 'methbags.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Crystallized methamphetamine ready for distribution.' },
-- ── COKE LAB ──────────────────────────────────────────────────────────────────
['coca_leaf'] = { name = 'coca_leaf', label = 'Coca Leaf', weight = 50, type = 'item', image = 'coca_leaf.png', unique = false, useable = false, shouldClose = true, combinable = nil, description = 'Raw coca leaf. Primary raw material for processing.' },
['coke'] = { name = 'coke', label = 'Base Powder', weight = 80, type = 'item', image = 'coke.png', unique = false, useable = false, shouldClose = true, combinable = nil, description = 'Unprocessed cocaine powder. Intermediate product.' },
['bakingsoda'] = { name = 'bakingsoda', label = 'Baking Soda', weight = 50, type = 'item', image = 'bakingsoda.png', unique = false, useable = false, shouldClose = true, combinable = nil, description = 'Sodium bicarbonate. Cutting agent for cocaine.' },
['loosecoke'] = { name = 'loosecoke', label = 'Cut Cocaine', weight = 80, type = 'item', image = 'loosecoke.png', unique = false, useable = false, shouldClose = true, combinable = nil, description = 'Cut cocaine ready for bagging.' },
['cokebaggy'] = { name = 'cokebaggy', label = 'Cocaine Baggy', weight = 100, type = 'item', image = 'cokebaggy.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Bagged cocaine ready for distribution.' },
-- ── WEED LAB ──────────────────────────────────────────────────────────────────
['wetcannabis'] = { name = 'wetcannabis', label = 'Wet Cannabis', weight = 100, type = 'item', image = 'wetcannabis.png', unique = false, useable = false, shouldClose = true, combinable = nil, description = 'Freshly harvested cannabis flower. Must be dried.' },
['drycannabis'] = { name = 'drycannabis', label = 'Dry Cannabis', weight = 60, type = 'item', image = 'drycannabis.png', unique = false, useable = false, shouldClose = true, combinable = nil, description = 'Dried cannabis ready for grinding.' },
['weedgrinder'] = { name = 'weedgrinder', label = 'Grinder', weight = 200, type = 'item', image = 'weedgrinder.png', unique = true, useable = true, shouldClose = true, combinable = nil, description = 'Herb grinder. Not consumed on use.' },
['grindedweed'] = { name = 'grindedweed', label = 'Ground Cannabis', weight = 40, type = 'item', image = 'grindedweed.png', unique = false, useable = false, shouldClose = true, combinable = nil, description = 'Ground cannabis ready for bagging.' },
['bluntwrap'] = { name = 'bluntwrap', label = 'Blunt Wrap', weight = 10, type = 'item', image = 'bluntwrap.png', unique = false, useable = false, shouldClose = true, combinable = nil, description = 'Rolling paper for blunts.' },
['blunt'] = { name = 'blunt', label = 'Blunt', weight = 30, type = 'item', image = 'blunt.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Rolled blunt ready for sale.' },
-- ── GANG CAD ──────────────────────────────────────────────────────────────────
['ilegal_cad'] = { name = 'ilegal_cad', label = 'Gang CAD', weight = 0, type = 'item', image = 'ilegal_cad.png', unique = false, useable = true, shouldClose = false, combinable = nil, description = 'Gang panel access credential. Not consumed on use.' },
-- ── GRAFFITI ──────────────────────────────────────────────────────────────────
['graffiti_spray'] = { name = 'graffiti_spray', label = 'Spray Can', weight = 300, type = 'item', image = 'graffiti_spray.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Aerosol spray can. Used to tag gang graffiti. Consumed on placement.' },
['graffiti_eraser'] = { name = 'graffiti_eraser', label = 'Cleaning Rag', weight = 100, type = 'item', image = 'graffiti_eraser.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Solvent-soaked rag. Used to clean graffiti tags. Consumed on use.' },Ejecuta el siguiente SQL contra tu base de datos (o pégalo en HeidiSQL / phpMyAdmin):
INSERT INTO `items` (`name`, `label`, `weight`, `rare`, `can_remove`) VALUES
-- METH LAB
('ephedrine', 'Ephedrine', 100, 0, 1),
('acetone', 'Acetone', 200, 0, 1),
('empty_weed_bag', 'Empty Bag', 10, 0, 1),
('methbags', 'Meth Bags', 150, 0, 1),
-- COKE LAB
('coca_leaf', 'Coca Leaf', 50, 0, 1),
('coke', 'Base Powder', 80, 0, 1),
('bakingsoda', 'Baking Soda', 50, 0, 1),
('loosecoke', 'Cut Cocaine', 80, 0, 1),
('cokebaggy', 'Cocaine Baggy', 100, 0, 1),
-- WEED LAB
('wetcannabis', 'Wet Cannabis', 100, 0, 1),
('drycannabis', 'Dry Cannabis', 60, 0, 1),
('weedgrinder', 'Grinder', 200, 1, 1),
('grindedweed', 'Ground Cannabis', 40, 0, 1),
('bluntwrap', 'Blunt Wrap', 10, 0, 1),
('blunt', 'Blunt', 30, 0, 1),
-- GANG CAD
('ilegal_cad', 'Gang CAD', 0, 0, 1),
-- GRAFFITI
('graffiti_spray', 'Spray Can', 300, 0, 1),
('graffiti_eraser', 'Cleaning Rag', 100, 0, 1);En ESX, rare = 1 marca un objeto como no apilable en algunas implementaciones antiguas de UI. Solo weedgrinder e ilegal_cad están marcados como raros/únicos en todos los formatos porque son herramientas, no consumibles.
Coloca los ficheros de imagen .png en la carpeta de imágenes de tu recurso de inventario:
Los nombres de fichero deben coincidir exactamente con el campo image (distingue mayúsculas y minúsculas en servidores Linux):
ephedrine.png acetone.png empty_weed_bag.png methbags.png
coca_leaf.png coke.png bakingsoda.png loosecoke.png
cokebaggy.png wetcannabis.png drycannabis.png weedgrinder.png
grindedweed.png bluntwrap.png blunt.png ilegal_cad.png
graffiti_spray.png graffiti_eraser.png