local QBCore = exports['qb-core']:GetCoreObject() -- Datenbank Tabelle erstellen MySQL.ready(function() MySQL.Async.execute([[ CREATE TABLE IF NOT EXISTS vehicle_rentals ( id INT AUTO_INCREMENT PRIMARY KEY, citizenid VARCHAR(50) NOT NULL, vehicle_model VARCHAR(50) NOT NULL, vehicle_plate VARCHAR(10) NOT NULL, rental_location VARCHAR(50) NOT NULL, start_time BIGINT NOT NULL, end_time BIGINT NOT NULL, price_per_hour INT NOT NULL, returned BOOLEAN DEFAULT FALSE, penalty_paid BOOLEAN DEFAULT FALSE, INDEX(citizenid), INDEX(vehicle_plate) ) ]]) end) -- Fahrzeug mieten QBCore.Functions.CreateCallback('vehiclerental:server:rentVehicle', function(source, cb, data) local Player = QBCore.Functions.GetPlayer(source) if not Player then return cb(false) end local totalCost = data.pricePerHour * data.hours local currentTime = os.time() local endTime = currentTime + (data.hours * 3600) -- Zahlung prüfen und abziehen local paymentSuccess = false if Config.UseOkokBanking then local bankMoney = exports['okokBanking']:GetAccount(Player.PlayerData.citizenid) if bankMoney and bankMoney >= totalCost then exports['okokBanking']:RemoveMoney(Player.PlayerData.citizenid, totalCost) paymentSuccess = true end else if Player.Functions.RemoveMoney('cash', totalCost) then paymentSuccess = true end end if not paymentSuccess then TriggerClientEvent('QBCore:Notify', source, 'Nicht genug Geld!', 'error') return cb(false) end -- Fahrzeug in Datenbank eintragen MySQL.Async.insert('INSERT INTO vehicle_rentals (citizenid, vehicle_model, vehicle_plate, rental_location, start_time, end_time, price_per_hour) VALUES (?, ?, ?, ?, ?, ?, ?)', { Player.PlayerData.citizenid, data.vehicleModel, data.plate, data.locationId, currentTime, endTime, data.pricePerHour }) TriggerClientEvent('QBCore:Notify', source, 'Fahrzeug erfolgreich gemietet für $' .. totalCost, 'success') cb(true) end) -- Fahrzeug zurückgeben QBCore.Functions.CreateCallback('vehiclerental:server:returnVehicle', function(source, cb, plate) local Player = QBCore.Functions.GetPlayer(source) if not Player then return cb(false) end MySQL.Async.fetchAll('SELECT * FROM vehicle_rentals WHERE citizenid = ? AND vehicle_plate = ? AND returned = FALSE', { Player.PlayerData.citizenid, plate }, function(result) if not result[1] then TriggerClientEvent('QBCore:Notify', source, 'Kein aktives Mietverhältnis für dieses Fahrzeug gefunden!', 'error') return cb(false) end 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 }) TriggerClientEvent('QBCore:Notify', source, 'Fahrzeug erfolgreich zurückgegeben!', 'success') cb(true) end) end) -- Mietzeit abfragen QBCore.Functions.CreateCallback('vehiclerental:server:getRentalInfo', function(source, cb) local Player = QBCore.Functions.GetPlayer(source) if not Player then return cb(nil) end MySQL.Async.fetchAll('SELECT * FROM vehicle_rentals WHERE citizenid = ? AND returned = FALSE', { Player.PlayerData.citizenid }, function(result) if not result[1] then return cb(nil) end local rentals = {} for i = 1, #result do local rental = result[i] local currentTime = os.time() local timeLeft = rental.end_time - currentTime table.insert(rentals, { vehicleModel = rental.vehicle_model, plate = rental.vehicle_plate, timeLeft = timeLeft, isOverdue = timeLeft < 0 }) end cb(rentals) end) end) -- Befehl für Mietzeit QBCore.Commands.Add('mietzeit', 'Zeige deine aktuelle Mietzeit an', {}, false, function(source, args) local Player = QBCore.Functions.GetPlayer(source) if not Player then return end MySQL.Async.fetchAll('SELECT * FROM vehicle_rentals WHERE citizenid = ? AND returned = FALSE', { Player.PlayerData.citizenid }, function(result) if not result or #result == 0 then TriggerClientEvent('QBCore:Notify', source, 'Du hast keine aktiven Mietverhältnisse!', 'error') return end for i = 1, #result do local rental = result[i] local currentTime = os.time() local timeLeft = rental.end_time - currentTime local timeText = "" if timeLeft < 0 then local hoursOverdue = math.ceil(math.abs(timeLeft) / 3600) timeText = "Überfällig um " .. hoursOverdue .. " Stunden" TriggerClientEvent('QBCore:Notify', source, rental.vehicle_model .. " (" .. rental.vehicle_plate .. "): " .. timeText, 'error') else local hoursLeft = math.floor(timeLeft / 3600) local minutesLeft = math.floor((timeLeft % 3600) / 60) timeText = hoursLeft .. "h " .. minutesLeft .. "m verbleibend" TriggerClientEvent('QBCore:Notify', source, rental.vehicle_model .. " (" .. rental.vehicle_plate .. "): " .. timeText, 'primary') end end end) end) -- Spieler Mietverhältnisse abrufen (VERBESSERT) QBCore.Functions.CreateCallback('vehiclerental:server:getPlayerRentals', function(source, cb) local Player = QBCore.Functions.GetPlayer(source) if not Player then return cb(nil) end MySQL.Async.fetchAll('SELECT * FROM vehicle_rentals WHERE citizenid = ? AND returned = FALSE', { Player.PlayerData.citizenid }, function(result) if not result or #result == 0 then return cb(nil) 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)