forked from Simnation/Main
ed
This commit is contained in:
parent
19928f3c5f
commit
90ab2c2b27
3 changed files with 326 additions and 219 deletions
|
@ -1,24 +1,41 @@
|
||||||
local QBCore = exports['qb-core']:GetCoreObject()
|
local QBCore = exports['qb-core']:GetCoreObject()
|
||||||
local spawnedNPCs = {}
|
local spawnedNPCs = {}
|
||||||
local currentRental = nil
|
local activeRentalVehicles = {}
|
||||||
|
|
||||||
-- NPCs spawnen
|
-- NPCs spawnen
|
||||||
CreateThread(function()
|
CreateThread(function()
|
||||||
|
-- Warte kurz, bis die Welt geladen ist
|
||||||
|
Wait(2000)
|
||||||
|
|
||||||
for i = 1, #Config.RentalLocations do
|
for i = 1, #Config.RentalLocations do
|
||||||
local location = Config.RentalLocations[i]
|
local location = Config.RentalLocations[i]
|
||||||
|
local modelHash = GetHashKey(location.npc.model)
|
||||||
|
|
||||||
RequestModel(location.npc.model)
|
-- Modell laden
|
||||||
while not HasModelLoaded(location.npc.model) do
|
RequestModel(modelHash)
|
||||||
Wait(1)
|
local timeout = 0
|
||||||
|
while not HasModelLoaded(modelHash) and timeout < 30 do
|
||||||
|
Wait(100)
|
||||||
|
timeout = timeout + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
local npc = CreatePed(4, location.npc.model, location.npc.coords.x, location.npc.coords.y, location.npc.coords.z - 1.0, location.npc.coords.w, false, true)
|
if HasModelLoaded(modelHash) then
|
||||||
|
-- NPC erstellen
|
||||||
|
local coords = location.npc.coords
|
||||||
|
local npc = CreatePed(4, modelHash, coords.x, coords.y, coords.z - 1.0, coords.w, false, false)
|
||||||
|
|
||||||
|
-- NPC-Eigenschaften setzen
|
||||||
FreezeEntityPosition(npc, true)
|
FreezeEntityPosition(npc, true)
|
||||||
SetEntityInvincible(npc, true)
|
SetEntityInvincible(npc, true)
|
||||||
SetBlockingOfNonTemporaryEvents(npc, true)
|
SetBlockingOfNonTemporaryEvents(npc, true)
|
||||||
|
SetPedDefaultComponentVariation(npc)
|
||||||
|
|
||||||
|
-- NPC speichern
|
||||||
spawnedNPCs[location.id] = npc
|
spawnedNPCs[location.id] = npc
|
||||||
|
|
||||||
|
-- Debug-Info
|
||||||
|
print("NPC spawned at location: " .. location.name)
|
||||||
|
|
||||||
-- QB-Target für NPC
|
-- QB-Target für NPC
|
||||||
exports['qb-target']:AddTargetEntity(npc, {
|
exports['qb-target']:AddTargetEntity(npc, {
|
||||||
options = {
|
options = {
|
||||||
|
@ -39,6 +56,9 @@ CreateThread(function()
|
||||||
},
|
},
|
||||||
distance = 2.0
|
distance = 2.0
|
||||||
})
|
})
|
||||||
|
else
|
||||||
|
print("Failed to load NPC model for location: " .. location.name)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -130,12 +150,18 @@ function spawnRentalVehicle(model, spawnPoint, plate)
|
||||||
TriggerEvent("vehiclekeys:client:SetOwner", plate)
|
TriggerEvent("vehiclekeys:client:SetOwner", plate)
|
||||||
SetModelAsNoLongerNeeded(model)
|
SetModelAsNoLongerNeeded(model)
|
||||||
|
|
||||||
-- Registriere das Fahrzeug im Parking-System
|
-- Speichere das Fahrzeug lokal
|
||||||
TriggerEvent('vehiclerental:client:vehicleRented', vehicle, plate)
|
activeRentalVehicles[plate] = vehicle
|
||||||
|
|
||||||
|
-- Speichere die initiale Position
|
||||||
|
local pos = GetEntityCoords(vehicle)
|
||||||
|
local rot = GetEntityRotation(vehicle)
|
||||||
|
TriggerServerEvent('vehiclerental:server:updatePosition', plate, pos, rot)
|
||||||
|
|
||||||
|
print("Neues Mietfahrzeug erstellt: " .. plate)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Fahrzeug zurückgeben
|
||||||
-- Fahrzeug zurückgeben (KORRIGIERT - ohne im Auto zu sitzen)
|
|
||||||
RegisterNetEvent('vehiclerental:client:returnVehicle', function(data)
|
RegisterNetEvent('vehiclerental:client:returnVehicle', function(data)
|
||||||
-- Hole alle aktiven Mietverhältnisse des Spielers
|
-- Hole alle aktiven Mietverhältnisse des Spielers
|
||||||
QBCore.Functions.TriggerCallback('vehiclerental:server:getPlayerRentals', function(rentals)
|
QBCore.Functions.TriggerCallback('vehiclerental:server:getPlayerRentals', function(rentals)
|
||||||
|
@ -171,17 +197,33 @@ end)
|
||||||
|
|
||||||
-- Spezifisches Fahrzeug zurückgeben
|
-- Spezifisches Fahrzeug zurückgeben
|
||||||
function returnSpecificVehicle(plate, locationId)
|
function returnSpecificVehicle(plate, locationId)
|
||||||
|
-- Finde die Location-Daten
|
||||||
|
local location = nil
|
||||||
|
for i = 1, #Config.RentalLocations do
|
||||||
|
if Config.RentalLocations[i].id == locationId then
|
||||||
|
location = Config.RentalLocations[i]
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not location then
|
||||||
|
QBCore.Functions.Notify('Fehler beim Finden des Rückgabeorts!', 'error')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Definiere den Rückgabeort
|
||||||
|
local returnPoint = vector3(location.returnPoint.x, location.returnPoint.y, location.returnPoint.z)
|
||||||
|
|
||||||
-- Finde das Fahrzeug in der Nähe
|
-- Finde das Fahrzeug in der Nähe
|
||||||
local playerPos = GetEntityCoords(PlayerPedId())
|
|
||||||
local vehicle = nil
|
local vehicle = nil
|
||||||
local closestDistance = 50.0 -- Maximale Entfernung
|
local closestDistance = 50.0 -- Maximale Suchentfernung
|
||||||
|
|
||||||
-- Suche nach dem Fahrzeug mit dem Kennzeichen
|
-- Suche nach dem Fahrzeug mit dem Kennzeichen
|
||||||
for veh in EnumerateVehicles() do
|
for veh in EnumerateVehicles() do
|
||||||
local vehPlate = GetVehicleNumberPlateText(veh)
|
local vehPlate = GetVehicleNumberPlateText(veh)
|
||||||
if string.gsub(vehPlate, "%s+", "") == string.gsub(plate, "%s+", "") then
|
if string.gsub(vehPlate, "%s+", "") == string.gsub(plate, "%s+", "") then
|
||||||
local vehPos = GetEntityCoords(veh)
|
local vehPos = GetEntityCoords(veh)
|
||||||
local distance = #(playerPos - vehPos)
|
local distance = #(returnPoint - vehPos)
|
||||||
|
|
||||||
if distance < closestDistance then
|
if distance < closestDistance then
|
||||||
vehicle = veh
|
vehicle = veh
|
||||||
|
@ -191,38 +233,137 @@ function returnSpecificVehicle(plate, locationId)
|
||||||
end
|
end
|
||||||
|
|
||||||
if not vehicle then
|
if not vehicle then
|
||||||
QBCore.Functions.Notify('Fahrzeug nicht in der Nähe gefunden! Bringe es zum Mietort zurück.', 'error')
|
QBCore.Functions.Notify('Fahrzeug nicht in der Nähe des Rückgabeorts gefunden!', 'error')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Prüfe ob das Fahrzeug am richtigen Ort ist
|
-- Prüfe ob das Fahrzeug nahe genug am Rückgabeort ist
|
||||||
local location = nil
|
|
||||||
for i = 1, #Config.RentalLocations do
|
|
||||||
if Config.RentalLocations[i].id == locationId then
|
|
||||||
location = Config.RentalLocations[i]
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if location then
|
|
||||||
local returnPos = vector3(location.returnPoint.x, location.returnPoint.y, location.returnPoint.z)
|
|
||||||
local vehPos = GetEntityCoords(vehicle)
|
local vehPos = GetEntityCoords(vehicle)
|
||||||
local distance = #(returnPos - vehPos)
|
local distance = #(returnPoint - vehPos)
|
||||||
|
|
||||||
if distance > 10.0 then
|
if distance > Config.MaxReturnDistance then
|
||||||
QBCore.Functions.Notify('Bringe das Fahrzeug näher zum Rückgabeort!', 'error')
|
QBCore.Functions.Notify('Das Fahrzeug muss näher am Rückgabeort sein! (Max. ' .. Config.MaxReturnDistance .. 'm)', 'error')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
-- Fahrzeug zurückgeben
|
-- Fahrzeug zurückgeben
|
||||||
QBCore.Functions.TriggerCallback('vehiclerental:server:returnVehicle', function(success)
|
QBCore.Functions.TriggerCallback('vehiclerental:server:returnVehicle', function(success)
|
||||||
if success then
|
if success then
|
||||||
DeleteVehicle(vehicle)
|
DeleteVehicle(vehicle)
|
||||||
|
activeRentalVehicles[plate] = nil
|
||||||
|
QBCore.Functions.Notify('Fahrzeug erfolgreich zurückgegeben!', 'success')
|
||||||
end
|
end
|
||||||
end, plate)
|
end, plate)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Lade alle aktiven Mietfahrzeuge
|
||||||
|
RegisterNetEvent('vehiclerental:client:loadRentals')
|
||||||
|
AddEventHandler('vehiclerental:client:loadRentals', function(rentals)
|
||||||
|
-- Lösche alle vorhandenen Mietfahrzeuge
|
||||||
|
for plate, vehicle in pairs(activeRentalVehicles) do
|
||||||
|
if DoesEntityExist(vehicle) then
|
||||||
|
DeleteVehicle(vehicle)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
activeRentalVehicles = {}
|
||||||
|
|
||||||
|
-- Spawne alle aktiven Mietfahrzeuge
|
||||||
|
for _, rental in ipairs(rentals) do
|
||||||
|
-- Prüfe, ob das Fahrzeug dem aktuellen Spieler gehört
|
||||||
|
local playerCitizenId = QBCore.Functions.GetPlayerData().citizenid
|
||||||
|
|
||||||
|
if rental.citizenid == playerCitizenId then
|
||||||
|
-- Spawne das Fahrzeug nur, wenn es eine Position hat
|
||||||
|
if rental.posX ~= 0 or rental.posY ~= 0 or rental.posZ ~= 0 then
|
||||||
|
Citizen.CreateThread(function()
|
||||||
|
local model = rental.vehicle_model
|
||||||
|
local plate = rental.vehicle_plate
|
||||||
|
|
||||||
|
-- Lade das Modell
|
||||||
|
RequestModel(model)
|
||||||
|
while not HasModelLoaded(model) do
|
||||||
|
Citizen.Wait(10)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Spawne das Fahrzeug
|
||||||
|
local vehicle = CreateVehicle(model,
|
||||||
|
rental.posX, rental.posY, rental.posZ,
|
||||||
|
rental.rotZ or 0.0, true, false)
|
||||||
|
|
||||||
|
-- Setze Eigenschaften
|
||||||
|
SetVehicleNumberPlateText(vehicle, plate)
|
||||||
|
SetEntityAsMissionEntity(vehicle, true, true)
|
||||||
|
SetVehicleDoorsLocked(vehicle, 2) -- Abgeschlossen
|
||||||
|
|
||||||
|
-- Setze Rotation
|
||||||
|
SetEntityRotation(vehicle,
|
||||||
|
rental.rotX or 0.0,
|
||||||
|
rental.rotY or 0.0,
|
||||||
|
rental.rotZ or 0.0,
|
||||||
|
2, true)
|
||||||
|
|
||||||
|
-- Gib dem Spieler die Schlüssel
|
||||||
|
TriggerEvent("vehiclekeys:client:SetOwner", plate)
|
||||||
|
|
||||||
|
-- Speichere das Fahrzeug lokal
|
||||||
|
activeRentalVehicles[plate] = vehicle
|
||||||
|
|
||||||
|
print("Mietfahrzeug geladen: " .. plate)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Fahrzeug zurückgegeben
|
||||||
|
RegisterNetEvent('vehiclerental:client:vehicleReturned')
|
||||||
|
AddEventHandler('vehiclerental:client:vehicleReturned', function(plate)
|
||||||
|
-- Lösche das Fahrzeug, wenn es existiert
|
||||||
|
if activeRentalVehicles[plate] and DoesEntityExist(activeRentalVehicles[plate]) then
|
||||||
|
DeleteVehicle(activeRentalVehicles[plate])
|
||||||
|
activeRentalVehicles[plate] = nil
|
||||||
|
print("Mietfahrzeug gelöscht: " .. plate)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Regelmäßiges Update der Fahrzeugpositionen
|
||||||
|
Citizen.CreateThread(function()
|
||||||
|
while true do
|
||||||
|
Citizen.Wait(30000) -- Alle 30 Sekunden
|
||||||
|
|
||||||
|
-- Update alle aktiven Mietfahrzeuge
|
||||||
|
for plate, vehicle in pairs(activeRentalVehicles) do
|
||||||
|
if DoesEntityExist(vehicle) then
|
||||||
|
local pos = GetEntityCoords(vehicle)
|
||||||
|
local rot = GetEntityRotation(vehicle)
|
||||||
|
TriggerServerEvent('vehiclerental:server:updatePosition', plate, pos, rot)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Wenn der Spieler das Fahrzeug verlässt, aktualisiere die Position
|
||||||
|
Citizen.CreateThread(function()
|
||||||
|
while true do
|
||||||
|
Citizen.Wait(500)
|
||||||
|
|
||||||
|
local playerPed = PlayerPedId()
|
||||||
|
local vehicle = GetVehiclePedIsIn(playerPed, true)
|
||||||
|
|
||||||
|
if vehicle ~= 0 then
|
||||||
|
local plate = GetVehicleNumberPlateText(vehicle)
|
||||||
|
|
||||||
|
-- Wenn es ein Mietfahrzeug ist und der Spieler es gerade verlassen hat
|
||||||
|
if activeRentalVehicles[plate] and not IsPedInVehicle(playerPed, vehicle, false) then
|
||||||
|
local pos = GetEntityCoords(vehicle)
|
||||||
|
local rot = GetEntityRotation(vehicle)
|
||||||
|
TriggerServerEvent('vehiclerental:server:updatePosition', plate, pos, rot)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
-- Fahrzeug-Enumerator
|
-- Fahrzeug-Enumerator
|
||||||
function EnumerateVehicles()
|
function EnumerateVehicles()
|
||||||
return coroutine.wrap(function()
|
return coroutine.wrap(function()
|
||||||
|
@ -236,7 +377,7 @@ function EnumerateVehicles()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Kennzeichen generieren (GEÄNDERT - RENTAL + 3 zufällige Zeichen)
|
-- Kennzeichen generieren (RENT + 4 zufällige Zeichen)
|
||||||
function GeneratePlate()
|
function GeneratePlate()
|
||||||
local plate = "RENT"
|
local plate = "RENT"
|
||||||
for i = 1, 4 do
|
for i = 1, 4 do
|
||||||
|
@ -258,24 +399,10 @@ AddEventHandler('onResourceStop', function(resourceName)
|
||||||
DeleteEntity(npc)
|
DeleteEntity(npc)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
|
||||||
-- Integration mit mh_Parking
|
|
||||||
RegisterNetEvent('vehiclerental:client:vehicleRented')
|
|
||||||
AddEventHandler('vehiclerental:client:vehicleRented', function(vehicle, plate)
|
|
||||||
-- Warte kurz, bis das Fahrzeug vollständig gespawnt ist
|
|
||||||
Citizen.Wait(1000)
|
|
||||||
|
|
||||||
-- Aktualisiere das Fahrzeug im Parking-System
|
for plate, vehicle in pairs(activeRentalVehicles) do
|
||||||
if DoesEntityExist(vehicle) then
|
if DoesEntityExist(vehicle) then
|
||||||
TriggerEvent("mh_Parking:updateVehicle", vehicle)
|
DeleteVehicle(vehicle)
|
||||||
print("Mietfahrzeug im Parking-System registriert: " .. plate)
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Wenn ein Mietfahrzeug zurückgegeben wird
|
|
||||||
RegisterNetEvent('vehiclerental:client:vehicleReturned')
|
|
||||||
AddEventHandler('vehiclerental:client:vehicleReturned', function(plate)
|
|
||||||
-- Entferne das Fahrzeug aus dem Parking-System
|
|
||||||
TriggerServerEvent("mh_Parking:deleteVehicle", plate, true)
|
|
||||||
print("Mietfahrzeug aus dem Parking-System entfernt: " .. plate)
|
|
||||||
end)
|
|
||||||
|
|
|
@ -3,7 +3,8 @@ Config = {}
|
||||||
Config.MaxRentalTime = 24 -- Maximale Mietdauer in Stunden
|
Config.MaxRentalTime = 24 -- Maximale Mietdauer in Stunden
|
||||||
Config.PenaltyPerHour = 100 -- Strafe pro Stunde Verspätung
|
Config.PenaltyPerHour = 100 -- Strafe pro Stunde Verspätung
|
||||||
Config.UseOkokBanking = false -- true für okokBanking, false für Bargeld
|
Config.UseOkokBanking = false -- true für okokBanking, false für Bargeld
|
||||||
Config.MaxReturnDistance = 10.0 -- Maximale Entfernung zum Rückgabepunkt in Metern
|
Config.MaxReturnDistance = 20.0 -- Maximale Entfernung zum Rückgabepunkt in Metern
|
||||||
|
Config.MaxOverdueHours = 24 -- Nach wie vielen Stunden überfällige Fahrzeuge automatisch zurückgegeben werden
|
||||||
|
|
||||||
Config.RentalLocations = {
|
Config.RentalLocations = {
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,23 +1,46 @@
|
||||||
local QBCore = exports['qb-core']:GetCoreObject()
|
|
||||||
|
|
||||||
-- Datenbank Tabelle erstellen
|
local QBCore = exports['qb-core']:GetCoreObject()
|
||||||
MySQL.ready(function()
|
local activeRentals = {}
|
||||||
MySQL.Async.execute([[
|
|
||||||
CREATE TABLE IF NOT EXISTS vehicle_rentals (
|
-- Lade alle aktiven Mietfahrzeuge beim Serverstart
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
Citizen.CreateThread(function()
|
||||||
citizenid VARCHAR(50) NOT NULL,
|
Wait(5000) -- Warte, bis die Datenbank bereit ist
|
||||||
vehicle_model VARCHAR(50) NOT NULL,
|
|
||||||
vehicle_plate VARCHAR(10) NOT NULL,
|
MySQL.Async.fetchAll('SELECT * FROM vehicle_rentals WHERE returned = FALSE', {}, function(results)
|
||||||
rental_location VARCHAR(50) NOT NULL,
|
if results and #results > 0 then
|
||||||
start_time BIGINT NOT NULL,
|
print("Lade " .. #results .. " aktive Mietfahrzeuge...")
|
||||||
end_time BIGINT NOT NULL,
|
|
||||||
price_per_hour INT NOT NULL,
|
for _, rental in ipairs(results) do
|
||||||
returned BOOLEAN DEFAULT FALSE,
|
activeRentals[rental.vehicle_plate] = rental
|
||||||
penalty_paid BOOLEAN DEFAULT FALSE,
|
end
|
||||||
INDEX(citizenid),
|
|
||||||
INDEX(vehicle_plate)
|
-- Benachrichtige alle Clients, dass sie die Fahrzeuge spawnen sollen
|
||||||
)
|
TriggerClientEvent('vehiclerental:client:loadRentals', -1, results)
|
||||||
]])
|
end
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Aktualisiere die Position eines Mietfahrzeugs
|
||||||
|
RegisterServerEvent('vehiclerental:server:updatePosition')
|
||||||
|
AddEventHandler('vehiclerental:server:updatePosition', function(plate, position, rotation)
|
||||||
|
if not plate or not position then return end
|
||||||
|
|
||||||
|
-- Aktualisiere in der Datenbank
|
||||||
|
MySQL.Async.execute('UPDATE vehicle_rentals SET posX = ?, posY = ?, posZ = ?, rotX = ?, rotY = ?, rotZ = ?, lastUpdated = CURRENT_TIMESTAMP WHERE vehicle_plate = ? AND returned = FALSE', {
|
||||||
|
position.x, position.y, position.z,
|
||||||
|
rotation.x, rotation.y, rotation.z,
|
||||||
|
plate
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Aktualisiere im Cache
|
||||||
|
if activeRentals[plate] then
|
||||||
|
activeRentals[plate].posX = position.x
|
||||||
|
activeRentals[plate].posY = position.y
|
||||||
|
activeRentals[plate].posZ = position.z
|
||||||
|
activeRentals[plate].rotX = rotation.x
|
||||||
|
activeRentals[plate].rotY = rotation.y
|
||||||
|
activeRentals[plate].rotZ = rotation.z
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Fahrzeug mieten
|
-- Fahrzeug mieten
|
||||||
|
@ -57,11 +80,24 @@ QBCore.Functions.CreateCallback('vehiclerental:server:rentVehicle', function(sou
|
||||||
currentTime,
|
currentTime,
|
||||||
endTime,
|
endTime,
|
||||||
data.pricePerHour
|
data.pricePerHour
|
||||||
})
|
}, function(rentalId)
|
||||||
|
-- Füge das Fahrzeug zum aktiven Cache hinzu
|
||||||
|
activeRentals[data.plate] = {
|
||||||
|
id = rentalId,
|
||||||
|
citizenid = Player.PlayerData.citizenid,
|
||||||
|
vehicle_model = data.vehicleModel,
|
||||||
|
vehicle_plate = data.plate,
|
||||||
|
rental_location = data.locationId,
|
||||||
|
start_time = currentTime,
|
||||||
|
end_time = endTime,
|
||||||
|
price_per_hour = data.pricePerHour,
|
||||||
|
returned = false
|
||||||
|
}
|
||||||
|
|
||||||
TriggerClientEvent('QBCore:Notify', source, 'Fahrzeug erfolgreich gemietet für $' .. totalCost, 'success')
|
TriggerClientEvent('QBCore:Notify', source, 'Fahrzeug erfolgreich gemietet für $' .. totalCost, 'success')
|
||||||
cb(true)
|
cb(true)
|
||||||
end)
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
-- Fahrzeug zurückgeben
|
-- Fahrzeug zurückgeben
|
||||||
QBCore.Functions.CreateCallback('vehiclerental:server:returnVehicle', function(source, cb, plate)
|
QBCore.Functions.CreateCallback('vehiclerental:server:returnVehicle', function(source, cb, plate)
|
||||||
|
@ -116,38 +152,47 @@ QBCore.Functions.CreateCallback('vehiclerental:server:returnVehicle', function(s
|
||||||
rental.id
|
rental.id
|
||||||
})
|
})
|
||||||
|
|
||||||
|
-- Aus dem aktiven Cache entfernen
|
||||||
|
activeRentals[plate] = nil
|
||||||
|
|
||||||
|
-- Benachrichtige alle Clients, dass das Fahrzeug zurückgegeben wurde
|
||||||
|
TriggerClientEvent('vehiclerental:client:vehicleReturned', -1, plate)
|
||||||
|
|
||||||
TriggerClientEvent('QBCore:Notify', source, 'Fahrzeug erfolgreich zurückgegeben!', 'success')
|
TriggerClientEvent('QBCore:Notify', source, 'Fahrzeug erfolgreich zurückgegeben!', 'success')
|
||||||
cb(true)
|
cb(true)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Mietzeit abfragen
|
-- Spieler Mietverhältnisse abrufen
|
||||||
QBCore.Functions.CreateCallback('vehiclerental:server:getRentalInfo', function(source, cb)
|
QBCore.Functions.CreateCallback('vehiclerental:server:getPlayerRentals', function(source, cb)
|
||||||
local Player = QBCore.Functions.GetPlayer(source)
|
local Player = QBCore.Functions.GetPlayer(source)
|
||||||
if not Player then return cb(nil) end
|
if not Player then return cb(nil) end
|
||||||
|
|
||||||
MySQL.Async.fetchAll('SELECT * FROM vehicle_rentals WHERE citizenid = ? AND returned = FALSE', {
|
MySQL.Async.fetchAll('SELECT * FROM vehicle_rentals WHERE citizenid = ? AND returned = FALSE', {
|
||||||
Player.PlayerData.citizenid
|
Player.PlayerData.citizenid
|
||||||
}, function(result)
|
}, function(result)
|
||||||
if not result[1] then
|
if not result or #result == 0 then
|
||||||
return cb(nil)
|
return cb(nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
local rentals = {}
|
|
||||||
for i = 1, #result do
|
|
||||||
local rental = result[i]
|
|
||||||
local currentTime = os.time()
|
local currentTime = os.time()
|
||||||
local timeLeft = rental.end_time - currentTime
|
for i = 1, #result do
|
||||||
|
-- Berechne verbleibende Zeit auf dem Server
|
||||||
|
result[i].timeLeft = result[i].end_time - currentTime
|
||||||
|
result[i].isOverdue = result[i].timeLeft < 0
|
||||||
|
|
||||||
table.insert(rentals, {
|
-- Formatiere die Zeit für die Anzeige
|
||||||
vehicleModel = rental.vehicle_model,
|
if result[i].isOverdue then
|
||||||
plate = rental.vehicle_plate,
|
local hoursOverdue = math.ceil(math.abs(result[i].timeLeft) / 3600)
|
||||||
timeLeft = timeLeft,
|
result[i].timeText = "(Überfällig um " .. hoursOverdue .. " Stunden)"
|
||||||
isOverdue = timeLeft < 0
|
else
|
||||||
})
|
local hoursLeft = math.floor(result[i].timeLeft / 3600)
|
||||||
|
local minutesLeft = math.floor((result[i].timeLeft % 3600) / 60)
|
||||||
|
result[i].timeText = "(" .. hoursLeft .. "h " .. minutesLeft .. "m verbleibend)"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
cb(rentals)
|
cb(result)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -184,115 +229,49 @@ QBCore.Commands.Add('mietzeit', 'Zeige deine aktuelle Mietzeit an', {}, false, f
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Spieler Mietverhältnisse abrufen (VERBESSERT)
|
-- Regelmäßige Überprüfung auf überfällige Fahrzeuge
|
||||||
QBCore.Functions.CreateCallback('vehiclerental:server:getPlayerRentals', function(source, cb)
|
Citizen.CreateThread(function()
|
||||||
local Player = QBCore.Functions.GetPlayer(source)
|
while true do
|
||||||
if not Player then return cb(nil) end
|
Citizen.Wait(60000) -- Überprüfe jede Minute
|
||||||
|
|
||||||
|
local currentTime = os.time()
|
||||||
|
local overdueVehicles = {}
|
||||||
|
|
||||||
|
-- Überprüfe alle aktiven Mietfahrzeuge
|
||||||
|
for plate, rental in pairs(activeRentals) do
|
||||||
|
if currentTime > rental.end_time + (Config.MaxOverdueHours * 3600) then
|
||||||
|
-- Fahrzeug ist zu lange überfällig, markiere es als zurückgegeben
|
||||||
|
MySQL.Async.execute('UPDATE vehicle_rentals SET returned = TRUE, penalty_paid = TRUE WHERE vehicle_plate = ? AND returned = FALSE', {
|
||||||
|
plate
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Füge es zur Liste der zu entfernenden Fahrzeuge hinzu
|
||||||
|
table.insert(overdueVehicles, plate)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Entferne überfällige Fahrzeuge aus dem Cache
|
||||||
|
for _, plate in ipairs(overdueVehicles) do
|
||||||
|
activeRentals[plate] = nil
|
||||||
|
-- Benachrichtige alle Clients, dass das Fahrzeug entfernt werden soll
|
||||||
|
TriggerClientEvent('vehiclerental:client:vehicleReturned', -1, plate)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Spieler verbindet sich
|
||||||
|
RegisterNetEvent('QBCore:Server:PlayerLoaded')
|
||||||
|
AddEventHandler('QBCore:Server:PlayerLoaded', function()
|
||||||
|
local src = source
|
||||||
|
local Player = QBCore.Functions.GetPlayer(src)
|
||||||
|
if not Player then return end
|
||||||
|
|
||||||
|
-- Sende dem Spieler seine aktiven Mietfahrzeuge
|
||||||
MySQL.Async.fetchAll('SELECT * FROM vehicle_rentals WHERE citizenid = ? AND returned = FALSE', {
|
MySQL.Async.fetchAll('SELECT * FROM vehicle_rentals WHERE citizenid = ? AND returned = FALSE', {
|
||||||
Player.PlayerData.citizenid
|
Player.PlayerData.citizenid
|
||||||
}, function(result)
|
}, function(results)
|
||||||
if not result or #result == 0 then
|
if results and #results > 0 then
|
||||||
return cb(nil)
|
TriggerClientEvent('vehiclerental:client:loadRentals', src, results)
|
||||||
end
|
|
||||||
|
|
||||||
local currentTime = os.time()
|
|
||||||
for i = 1, #result do
|
|
||||||
-- Berechne verbleibende Zeit auf dem Server
|
|
||||||
result[i].timeLeft = result[i].end_time - currentTime
|
|
||||||
result[i].isOverdue = result[i].timeLeft < 0
|
|
||||||
|
|
||||||
-- Formatiere die Zeit für die Anzeige
|
|
||||||
if result[i].isOverdue then
|
|
||||||
local hoursOverdue = math.ceil(math.abs(result[i].timeLeft) / 3600)
|
|
||||||
result[i].timeText = "(Überfällig um " .. hoursOverdue .. " Stunden)"
|
|
||||||
else
|
|
||||||
local hoursLeft = math.floor(result[i].timeLeft / 3600)
|
|
||||||
local minutesLeft = math.floor((result[i].timeLeft % 3600) / 60)
|
|
||||||
result[i].timeText = "(" .. hoursLeft .. "h " .. minutesLeft .. "m verbleibend)"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
cb(result)
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
-- Funktion zum Entfernen von Mietfahrzeugen aus dem Parking-System
|
|
||||||
function RemoveRentalFromParking(plate)
|
|
||||||
-- Entferne das Fahrzeug aus dem mh_Parking System
|
|
||||||
TriggerEvent("mh_Parking:removeVehicle", plate)
|
|
||||||
|
|
||||||
-- Lösche es auch aus der Datenbank des Parking-Systems
|
|
||||||
MySQL.Async.execute("DELETE FROM vehicle_parking WHERE plate = @plate", {
|
|
||||||
["@plate"] = plate
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Wenn ein Fahrzeug zurückgegeben wird, entferne es aus dem Parking-System
|
|
||||||
RegisterNetEvent('vehiclerental:server:vehicleReturned')
|
|
||||||
AddEventHandler('vehiclerental:server:vehicleReturned', function(plate)
|
|
||||||
RemoveRentalFromParking(plate)
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- Modifiziere die bestehende returnVehicle Callback-Funktion
|
|
||||||
local originalReturnCallback = QBCore.Functions.CreateCallback('vehiclerental:server:returnVehicle')
|
|
||||||
QBCore.Functions.CreateCallback('vehiclerental:server:returnVehicle', function(source, cb, plate)
|
|
||||||
-- Wenn das Fahrzeug erfolgreich zurückgegeben wurde
|
|
||||||
MySQL.Async.fetchAll('SELECT * FROM vehicle_rentals WHERE vehicle_plate = ? AND returned = FALSE', {
|
|
||||||
plate
|
|
||||||
}, function(result)
|
|
||||||
if result[1] then
|
|
||||||
-- Führe die normale Rückgabe durch
|
|
||||||
local Player = QBCore.Functions.GetPlayer(source)
|
|
||||||
local rental = result[1]
|
|
||||||
local currentTime = os.time()
|
|
||||||
local penalty = 0
|
|
||||||
|
|
||||||
-- Strafe berechnen wenn verspätet
|
|
||||||
if currentTime > rental.end_time then
|
|
||||||
local hoursLate = math.ceil((currentTime - rental.end_time) / 3600)
|
|
||||||
penalty = hoursLate * Config.PenaltyPerHour
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Strafe abziehen falls vorhanden
|
|
||||||
if penalty > 0 then
|
|
||||||
local penaltyPaid = false
|
|
||||||
if Config.UseOkokBanking then
|
|
||||||
local bankMoney = exports['okokBanking']:GetAccount(Player.PlayerData.citizenid)
|
|
||||||
if bankMoney and bankMoney >= penalty then
|
|
||||||
exports['okokBanking']:RemoveMoney(Player.PlayerData.citizenid, penalty)
|
|
||||||
penaltyPaid = true
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if Player.Functions.RemoveMoney('cash', penalty) then
|
|
||||||
penaltyPaid = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if penaltyPaid then
|
|
||||||
TriggerClientEvent('QBCore:Notify', source, 'Verspätungsstrafe von $' .. penalty .. ' wurde abgezogen!', 'error')
|
|
||||||
else
|
|
||||||
TriggerClientEvent('QBCore:Notify', source, 'Nicht genug Geld für Verspätungsstrafe!', 'error')
|
|
||||||
return cb(false)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Mietverhältnis als zurückgegeben markieren
|
|
||||||
MySQL.Async.execute('UPDATE vehicle_rentals SET returned = TRUE, penalty_paid = ? WHERE id = ?', {
|
|
||||||
penalty > 0,
|
|
||||||
rental.id
|
|
||||||
})
|
|
||||||
|
|
||||||
-- Entferne das Fahrzeug aus dem Parking-System
|
|
||||||
RemoveRentalFromParking(plate)
|
|
||||||
|
|
||||||
-- Benachrichtige alle Clients
|
|
||||||
TriggerClientEvent('vehiclerental:client:vehicleReturned', -1, plate)
|
|
||||||
|
|
||||||
TriggerClientEvent('QBCore:Notify', source, 'Fahrzeug erfolgreich zurückgegeben!', 'success')
|
|
||||||
cb(true)
|
|
||||||
else
|
|
||||||
TriggerClientEvent('QBCore:Notify', source, 'Kein aktives Mietverhältnis für dieses Fahrzeug gefunden!', 'error')
|
|
||||||
cb(false)
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue