======================================================================= ⚙️ INSTRUCCIONES DE INSTALACIÓN EN EL FRAMEWORK (qb-core) ⚙️
UBICACIÓN DEL CÓDIGO:
Debes pegar el código que hay más abajo exactamente al FINAL del archivo:
Ruta: qb-core/server/main.lua
Por temas de seguridad de FiveM, un script (como este concesionario) NO tiene permisos para editar o sobrescribir archivos que pertenecen a otro script distinto (en este caso, qb-core). Como este concesionario necesita crear o modificar vehículos y trabajos (jobs) desde el juego y guardarlos para siempre, necesitamos "engañar" al sistema creando estos dos "exports" (puertas traseras legales) directamente dentro de qb-core. De esta forma, cuando este concesionario quiere guardar un coche nuevo, le "pide el favor" a qb-core mediante este export, y es el propio qb-core quien modifica sus propios archivos sin dar errores de permisos. Si no pones esto, al reiniciar el servidor se perderán todos los coches que hayas añadido in-game.
-- =================================================================
-- EXPORT: GUARDADO DE JOBS DESDE SCRIPTS EXTERNOS
-- =================================================================
exports('SaveJobsFile', function(serializedData)
local str = "QBShared = QBShared or {}\nQBShared.ForceJobDefaultDutyAtLogin = true\n\nQBShared.Jobs = {\n" .. serializedData .. "\n}\n"
-- Al ejecutarse desde dentro de qb-core, SaveResourceFile funciona al 100%
local result = SaveResourceFile(GetCurrentResourceName(), "shared/jobs.lua", str, -1)
return result
end)
-- =================================================================
-- EXPORT: GUARDADO DE VEHÍCULOS DESDE SCRIPTS EXTERNOS
-- =================================================================
exports('SaveVehiclesFile', function(data)
-- Verificamos que el archivo existe antes de intentar escribir
local loadFile = LoadResourceFile('qb-core', 'shared/vehicles.lua')
if not loadFile then
return false
end
-- Abrimos el archivo en modo escritura ('w')
local file = io.open(GetResourcePath('qb-core') .. '/shared/vehicles.lua', 'w')
if file then
-- Reconstruimos la cabecera original del archivo y metemos los datos
file:write("QBShared = QBShared or {}\nQBShared.Vehicles = {\n" .. data .. "\n}")
file:close()
return true
end
return false
end)function PaycheckInterval()
if not next(QBCore.Players) then
SetTimeout(QBCore.Config.Money.PayCheckTimeOut * (60 * 1000), PaycheckInterval) -- Prevent paychecks from stopping forever once 0 players
return
end
for _, Player in pairs(QBCore.Players) do
if not Player then
return
end
-- [MODIFICACIÓN DP-VEHICLESHOP]: Excepción para los concesionarios
local jobName = Player.PlayerData.job.name
local isDealershipJob = (jobName == 'cardealer' or jobName == 'motorcycledealer' or jobName == 'airdealer' or jobName == 'boatdealer' or jobName == 'vipdealer' or jobName == 'useddealer')
-- Si NO es un trabajo de concesionario, QBCore paga normalmente con DP-Banking
if not isDealershipJob then
local payment = QBShared.Jobs[Player.PlayerData.job.name]['grades'][tostring(Player.PlayerData.job.grade.level)].payment
if not payment then
payment = Player.PlayerData.job.payment
end
if Player.PlayerData.job and payment > 0 and (QBShared.Jobs[Player.PlayerData.job.name].offDutyPay or Player.PlayerData.job.onduty) then
if QBCore.Config.Money.PayCheckSociety then
local account = exports['DP-Banking']:GetAccountBalance(Player.PlayerData.job.name)
if account ~= 0 then
if account < payment then
TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('error.company_too_poor'), 'error')
else
Player.Functions.AddMoney('bank', payment, 'paycheck')
exports['DP-Banking']:RemoveMoney(Player.PlayerData.job.name, payment, 'Employee Paycheck')
TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', {
value = payment
}))
end
else
Player.Functions.AddMoney('bank', payment, 'paycheck')
TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', {
value = payment
}))
end
else
Player.Functions.AddMoney('bank', payment, 'paycheck')
TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', {
value = payment
}))
end
end
end
end
SetTimeout(QBCore.Config.Money.PayCheckTimeOut * (60 * 1000), PaycheckInterval)
end=======================================================================
======================================================================= 📋 DP-VEHICLESHOP - HOJA DE RUTA EXPLICADA 📋
DP-GARAGES: - Crear un export en el DP-Garages, para que en el garaje salga cuantos % o cuanto dinero queda por pagar, o cuanto tiempo...
VISTA PREVIA: La vista previa va perfecto para CARS y BIKES... pero hay que configurarlo para que vaya con todos los demas... que no lo hace bien, debe hacerlo con el de BOATS, PLANES, etc... CONFIGURACIÓN DEL PERSONAL: Hacerlo enterito, ya que creo que no va nada... CONFIGURACIÓN DE LA EMPRESA: Hacerlo enterito, ya que nada de esto esta funcionando...
- REDISEÑO: La lista actual de este comando es horrible. Cambiar el diseño y asegurar que los modales (ventanas emergentes) sean totalmente distintos visualmente a los del concesionario normal.
- INTEGRACIÓN: Vincularlo al 'qb-jobmenu' (menú radial o de trabajo de qb-core).
- NUEVAS OPCIONES:
- Pegar el vehículo al suelo (stance/drop).
- Rotación automática de exhibición.
- Encender / Apagar el motor a distancia.
- Dar acelerones (Revving) para que los clientes escuchen el motor a full sin que el trabajador tenga que subirse al coche.
LOGS Y PERMISOS: Comprobar que absolutamente todos los botones generen logs, y que todos y cada uno de los rangos (jefe, empleado, etc.) bloqueen correctamente lo que no deben tocar. OPTIMIZACIÓN: Optimizar el client/server/javascript haciendolos que no se repitan cosas, y mejorando todo, fallos, errores. =======================================================================
Rol: Actúa como un desarrollador Senior o Experto en FiveM, especializado en el framework QB-Core, programación Lua (Cliente/Servidor), bases de datos SQL y desarrollo de interfaces modernas de usuario (NUI) utilizando HTML5, CSS3 avanzado y JavaScript.
Contexto del Proyecto:
Hace meses empecé un gran proyecto ya que no encontraba nada que fuera GRATIS y tuviera TODO lo que YO quería en un script de concesionario, por lo que tome la decisión de escribirla desde cero a mi gusto. El resultado es mi propio script llamado DP-VehicleShop.
Tiene muchísimas mecánicas, funciones y lógicas personalizadas que otros concesionarios/scripts similares no tienen o si lo tienen son de pago (mas de 30$).
Estructura del Proyecto:
A continuación te presento el árbol de archivos actual de DP-VehicleShop para que sepas dónde está cada cosa:
DP-VehicleShop ├── 📁 Images (Can Remove it if u want) (Imágenes que de demostración) │ └── 🖼️ Miniaturas YT.png ├── 📁 client │ └── 📄 cl_main.lua ├── 📁 server │ └── 📄 sv_main.lua ├── 📁 ui │ ├── 📁 veh_custom (Imágenes de vehículos CUSTOM para el bossmenu) │ ├── 🌐 index.html │ ├── 📄 script.js │ └── 🎨 style.css ├── ⚙️ .gitignore ├── 📝 README.md ├── 📄 config.lua └── 📄 fxmanifest.lua
Reglas de Trabajo:
- Código Custom: Como es una escritura masiva completamente hecha por mi, NO asumas que el código funciona exactamente igual que otros
vehicleshops. Si necesitas saber cómo hace algo mi script, pídeme que te pase el archivo o la función correspondiente. - Precisión: Cuando te pida añadir o arreglar algo, sé directo, conciso y dime exactamente en qué archivo y en qué línea aproximada o bloque debo hacer el cambio.
Instrucción inicial: Si has entendido el proyecto, la estructura y las reglas, responde ÚNICAMENTE con el siguiente mensaje: "✅ Contexto de DP-VehicleShop asimilado con éxito. Entiendo que es un Concesionario altamente customizado con bossmenu y controladores/Expositores, funcionando en SQL, JS y LUA. Estoy listo para programar. ¿Qué archivo, característica o error quieres que abordemos primero?"
/Miniaturas YT.png)