Sistema de alquiler de vehículos para FiveM: programa vehículos temporales
Añade vehículos de alquiler a tu servidor FiveM con llaves temporales, depósitos y devolución automática. Scripts para QBCore, ESX y standalone.
Agency Scripts
Fundador y desarrollador principal en Agency Scripts
Por qué los sistemas de alquiler mejoran el roleplay
No todos los jugadores de un servidor de roleplay tienen un vehículo, sobre todo los personajes nuevos que acaban de empezar. Un sistema de alquiler de coches y motos cubre esa necesidad al ofrecer transporte temporal a precios asequibles, crear oportunidades naturales de roleplay en los mostradores de alquiler y dar a los jugadores nuevos la libertad de explorar el mapa sin depender del transporte público ni tener que ir a pie. Además del transporte básico, los sistemas de alquiler permiten hacer roleplay turístico, donde los visitantes alquilan descapotables para recorrer paisajes, realizar trabajos de reparto que requieren tipos de vehículos específicos y organizar eventos donde los jugadores necesitan vehículos iguales para paseos en grupo o carreras. El sistema también genera un flujo de ingresos pasivos para la economía del servidor mediante las tarifas de alquiler, los depósitos por daños y las penalizaciones por devolver los vehículos tarde.
Configuración de flotas y categorías de vehículos
Organiza tu flota de alquiler en categorías que se adapten a las distintas necesidades y presupuestos de los jugadores. Los vehículos económicos ofrecen transporte básico y asequible, los coches de gama media ofrecen más comodidad y rendimiento, los vehículos prémium son ideales para experiencias de lujo y las motocicletas ofrecen una alternativa de dos ruedas. Cada categoría debe incluir varias opciones de vehículos con precios claros. Incluye tarifas por hora y por día para que los jugadores puedan elegir la opción más económica según sus necesidades. Define la flota en una tabla de configuración que especifique todos los vehículos disponibles junto con su precio de alquiler, depósito requerido, categoría y modelo de aparición:
Config.RentalLocations = {
['airport'] = {
label = 'LS Airport Car Rental',
pedModel = 's_f_y_airhostess_01',
pedCoords = vector4(-1037.34, -2736.82, 20.17, 238.52),
spawnPoint = vector4(-1029.12, -2728.91, 20.17, 148.76),
returnZone = vector3(-1035.00, -2730.00, 20.17),
returnRadius = 10.0,
categories = {'economy', 'midrange', 'premium', 'motorcycle'},
},
['downtown'] = {
label = 'Downtown Bike Rental',
pedModel = 'a_m_y_business_02',
pedCoords = vector4(-259.68, -892.41, 31.08, 69.24),
spawnPoint = vector4(-264.30, -888.12, 31.08, 339.87),
returnZone = vector3(-260.00, -890.00, 31.08),
returnRadius = 8.0,
categories = {'motorcycle', 'bicycle'},
},
}
Config.RentalFleet = {
economy = {
{model = 'blista', label = 'Blista', priceHour = 150, priceDay = 800, deposit = 500},
{model = 'asea', label = 'Asea', priceHour = 120, priceDay = 650, deposit = 400},
{model = 'stanier', label = 'Stanier', priceHour = 130, priceDay = 700, deposit = 450},
},
midrange = {
{model = 'schafter2', label = 'Schafter', priceHour = 300, priceDay = 1600, deposit = 1000},
{model = 'oracle', label = 'Oracle', priceHour = 280, priceDay = 1500, deposit = 900},
},
premium = {
{model = 'felon', label = 'Felon GT', priceHour = 600, priceDay = 3200, deposit = 2500},
{model = 'exemplar', label = 'Exemplar', priceHour = 550, priceDay = 3000, deposit = 2000},
},
motorcycle = {
{model = 'pcj', label = 'PCJ-600', priceHour = 100, priceDay = 500, deposit = 300},
{model = 'sanchez', label = 'Sanchez', priceHour = 80, priceDay = 400, deposit = 250},
},
bicycle = {
{model = 'cruiser', label = 'Cruiser Bike', priceHour = 30, priceDay = 150, deposit = 50},
{model = 'tribike', label = 'Tri-Cycles Race', priceHour = 25, priceDay = 120, deposit = 50},
},
}
Proceso de alquiler e interfaz NUI
El proceso de alquiler comienza cuando un jugador se acerca al NPC del mostrador de alquiler. Mediante un sistema de interacción o una comprobación de proximidad, abre un menú NUI que muestre las categorías de vehículos disponibles y opciones de filtrado. Cada vehículo anunciado debe mostrar el nombre del modelo, una imagen de vista previa si es posible, las tarifas por hora y por día, el depósito requerido y su disponibilidad. Cuando el jugador selecciona un vehículo y confirma la duración del alquiler, el servidor procesa la transacción. El cargo total corresponde a la tarifa de alquiler por el período seleccionado más el depósito por daños. El sistema retiene el depósito y lo devuelve cuando se entrega el vehículo sin daños. Implementa la confirmación del alquiler como un evento del servidor que valide que el jugador tiene fondos suficientes, compruebe que el vehículo seleccionado está disponible, cobre al jugador y genere el vehículo de alquiler en el punto de aparición designado:
RegisterNetEvent('rental:server:rentVehicle', function(locationId, vehicleModel, duration)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
local location = Config.RentalLocations[locationId]
if not location then return end
-- Check if player already has an active rental
if ActiveRentals[Player.PlayerData.citizenid] then
TriggerClientEvent('QBCore:Notify', src, 'You already have an active rental', 'error')
return
end
-- Find vehicle config
local vehicleConfig = nil
for _, category in pairs(Config.RentalFleet) do
for _, v in ipairs(category) do
if v.model == vehicleModel then
vehicleConfig = v
break
end
end
if vehicleConfig then break end
end
if not vehicleConfig then return end
-- Calculate cost
local rentalFee = duration == 'day' and vehicleConfig.priceDay or vehicleConfig.priceHour
local totalCost = rentalFee + vehicleConfig.deposit
if Player.Functions.GetMoney('bank') < totalCost then
TriggerClientEvent('QBCore:Notify', src, 'Insufficient funds. Need $' .. totalCost, 'error')
return
end
-- Charge player
Player.Functions.RemoveMoney('bank', totalCost, 'vehicle-rental')
-- Generate rental plate
local plate = 'RNT' .. math.random(10000, 99999)
-- Store active rental
ActiveRentals[Player.PlayerData.citizenid] = {
model = vehicleModel,
plate = plate,
deposit = vehicleConfig.deposit,
rentalFee = rentalFee,
startTime = os.time(),
duration = duration,
expiresAt = os.time() + (duration == 'day' and 86400 or 3600),
locationId = locationId,
initialHealth = 1000,
}
TriggerClientEvent('rental:client:spawnVehicle', src, vehicleModel, plate, location.spawnPoint)
TriggerClientEvent('QBCore:Notify', src, 'Vehicle rented! Return before your time expires.', 'success')
end)
Depósito por daños y mecánicas de devolución
El sistema de depósitos por daños responsabiliza a los jugadores por el trato que dan a los vehículos de alquiler. Cuando se devuelve el vehículo, compara sus valores de salud actuales con los valores iniciales registrados al alquilarlo. Los vehículos de GTA tienen valores de salud independientes para el motor, la carrocería y cada uno de sus componentes, lo que te permite evaluar los daños con precisión. Calcula el coste de reparación según los daños sufridos y descuéntalo del depósito antes de devolver el resto. Si los daños superan el importe del depósito, el jugador no recibe ningún reembolso y se le puede cobrar una tarifa adicional. Si el vehículo se devuelve en perfecto estado, se reembolsa el depósito completo. Este sistema fomenta la conducción cuidadosa sin penalizar por arañazos leves, inevitables debido a la física de conducción de GTA:
RegisterNetEvent('rental:server:returnVehicle', function(vehicleNet)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
local citizenid = Player.PlayerData.citizenid
local rental = ActiveRentals[citizenid]
if not rental then return end
local vehicle = NetworkGetEntityFromNetworkId(vehicleNet)
if not DoesEntityExist(vehicle) then return end
-- Check plate matches
local plate = GetVehicleNumberPlateText(vehicle)
if plate:trim() ~= rental.plate then
TriggerClientEvent('QBCore:Notify', src, 'This is not your rental vehicle', 'error')
return
end
-- Calculate damage
local bodyHealth = GetVehicleBodyHealth(vehicle)
local engineHealth = GetVehicleEngineHealth(vehicle)
local damagePercent = 1.0 - ((bodyHealth + engineHealth) / 2000.0)
local repairCost = math.floor(rental.deposit * damagePercent)
-- Calculate late fee
local lateFee = 0
if os.time() > rental.expiresAt then
local overHours = math.ceil((os.time() - rental.expiresAt) / 3600)
lateFee = overHours * 200
end
-- Refund deposit minus costs
local refund = math.max(0, rental.deposit - repairCost - lateFee)
if refund > 0 then
Player.Functions.AddMoney('bank', refund, 'rental-deposit-refund')
end
DeleteEntity(vehicle)
ActiveRentals[citizenid] = nil
local message = string.format('Vehicle returned. Deposit: $%d | Repairs: $%d | Late fee: $%d | Refund: $%d',
rental.deposit, repairCost, lateFee, refund)
TriggerClientEvent('QBCore:Notify', src, message, refund > 0 and 'success' or 'warning')
end)
Sistema de caducidad y devolución automática
Los vehículos de alquiler no deberían permanecer activos indefinidamente. Implementa un sistema de temporizador que haga un seguimiento de cuándo vence cada alquiler y actúe en consecuencia. Envía una notificación al jugador treinta minutos antes del vencimiento, otra cuando falten diez minutos y una última advertencia cuando falten cinco minutos. Cuando venza el alquiler, empieza a cobrar recargos por minuto de retraso hasta alcanzar un límite máximo. Si el jugador no devuelve el vehículo durante el período de gracia posterior al vencimiento, elimina automáticamente el vehículo y confisca todo el depósito. Esto evita que los vehículos de alquiler abandonados llenen el servidor. La comprobación del vencimiento debe ejecutarse periódicamente en el servidor, recorriendo todos los alquileres activos y actuando según el tiempo restante. Guarda el ID de red del vehículo para poder eliminarlo a distancia si es necesario, y contempla el caso de que el vehículo se destruya antes de que venza el alquiler, cerrándolo automáticamente y confiscando el depósito completo.
Varias ubicaciones de alquiler
Coloca los puntos de alquiler en lugares estratégicos del mapa donde el transporte temporal tenga más sentido. El aeropuerto es una opción obvia, ya que atiende a los jugadores que acaban de llegar a la ciudad. Las ubicaciones del centro, cerca de edificios gubernamentales, atienden a los jugadores que asisten a juicios o reuniones de negocios. Las ubicaciones de la playa ofrecen motocicletas y bicicletas para actividades recreativas a lo largo de la costa. Cada ubicación puede ofrecer una selección distinta de la flota: el aeropuerto tendrá toda la gama, desde vehículos económicos hasta prémium, mientras que las ubicaciones de la playa solo ofrecerán motocicletas y bicicletas. Personaliza el modelo del NPC de cada ubicación para que encaje con el entorno. Los alquileres del aeropuerto usan un modelo profesional de negocios, los de la playa uno informal de surfista y los del centro uno de empleado con traje. Esta atención al detalle hace que cada punto de alquiler parezca un negocio distinto, en vez de una copia idéntica del mismo sistema.
Seguimiento GPS y medidas antirrobo
Los vehículos de alquiler deberían tener seguimiento GPS integrado para que la empresa de alquiler y el jugador puedan localizarlos en cualquier momento. Muestra la ubicación del vehículo de alquiler en el mapa del jugador con un icono de blip distintivo. Si el vehículo se aleja más allá de un límite configurable, envía una notificación de advertencia. Implementa medidas antirrobo que impidan que otros jugadores guarden o aparquen en un garaje un vehículo de alquiler, para garantizar que siga bajo el control del sistema de alquileres. Cuando un jugador intente guardar un vehículo de alquiler en su garaje personal, el sistema debe bloquear la acción con una notificación que explique que no se pueden guardar vehículos de alquiler. Para las motocicletas y bicicletas, añade un candado virtual que solo pueda abrir el jugador que las alquiló, para evitar robos oportunistas. Si roban un vehículo de alquiler, el jugador que lo alquiló debería poder denunciarlo mediante una aplicación del teléfono, lo que activa una señal GPS que le ayuda a localizarlo. Registra el kilometraje total durante el alquiler para posibles recargos por kilometraje elevado, añadiendo otra capa de gestión realista de los alquileres de vehículos.
Integración con negocios y alquileres de propiedad de los jugadores
En servidores con un sistema de propiedad de negocios, permite que los jugadores compren y gestionen su propio negocio de alquileres. El propietario del negocio configura la flota comprando vehículos para añadirlos al grupo de alquileres, fija los precios, contrata empleados para atender el mostrador y recauda los ingresos de los alquileres. Los propietarios de negocios deberían tener un panel de gestión que muestre los alquileres activos, los ingresos diarios, el nivel de utilización de la flota y los costes de mantenimiento de los vehículos que acumulan daños con el paso de los alquileres. Los empleados pueden encargarse de las operaciones de atención al público, como tramitar alquileres y devoluciones, inspeccionar los vehículos devueltos para detectar daños y escalar las disputas al propietario. Este enfoque impulsado por los jugadores transforma el sistema de alquileres, de una mecánica de juego estática a un negocio dinámico que refleja el espíritu emprendedor de los servidores de roleplay y crea oportunidades de empleo para los jugadores que prefieren los roles de atención al cliente a los de acción intensa.