forked from Simnation/Main
206 lines
7.4 KiB
Lua
206 lines
7.4 KiB
Lua
![]() |
local QBCore = exports['qb-core']:GetCoreObject()
|
||
|
|
||
|
-- BAC-Abbaurate (wie viel BAC pro Minute abnimmt)
|
||
|
local BAC_DECAY_RATE = Config.BACDecayRate
|
||
|
|
||
|
-- Player BAC Cache um übermäßige Datenbankaufrufe zu vermeiden
|
||
|
local playerBAC = {}
|
||
|
|
||
|
-- Funktion zum Aktualisieren des BAC-Levels eines Spielers
|
||
|
local function UpdatePlayerBAC(citizenid, addAmount)
|
||
|
-- Initialisieren, falls nicht vorhanden
|
||
|
if not playerBAC[citizenid] then
|
||
|
playerBAC[citizenid] = {
|
||
|
bac = 0.0,
|
||
|
lastUpdated = os.time()
|
||
|
}
|
||
|
end
|
||
|
|
||
|
-- Zeitbasierten Abbau berechnen
|
||
|
local currentTime = os.time()
|
||
|
local minutesPassed = (currentTime - playerBAC[citizenid].lastUpdated) / 60
|
||
|
|
||
|
-- Abbau anwenden, aber nicht unter 0
|
||
|
local decayAmount = BAC_DECAY_RATE * minutesPassed
|
||
|
local newBAC = math.max(0.0, playerBAC[citizenid].bac - decayAmount)
|
||
|
|
||
|
-- Neuen Alkoholwert hinzufügen
|
||
|
newBAC = newBAC + addAmount
|
||
|
|
||
|
-- Bei realistischem Maximum begrenzen (0.5% wäre tödlich)
|
||
|
newBAC = math.min(0.5, newBAC)
|
||
|
|
||
|
-- Cache aktualisieren
|
||
|
playerBAC[citizenid] = {
|
||
|
bac = newBAC,
|
||
|
lastUpdated = currentTime
|
||
|
}
|
||
|
|
||
|
-- Datenbank aktualisieren
|
||
|
MySQL.Async.execute('INSERT INTO player_bac (citizenid, bac_level) VALUES (?, ?) ON DUPLICATE KEY UPDATE bac_level = ?, last_updated = CURRENT_TIMESTAMP',
|
||
|
{citizenid, newBAC, newBAC})
|
||
|
end
|
||
|
|
||
|
-- Funktion zum Abrufen des aktuellen BAC-Levels eines Spielers mit Abbauberechnung
|
||
|
local function GetCurrentBAC(citizenid)
|
||
|
-- Wenn wir Cache-Daten haben
|
||
|
if playerBAC[citizenid] then
|
||
|
local currentTime = os.time()
|
||
|
local minutesPassed = (currentTime - playerBAC[citizenid].lastUpdated) / 60
|
||
|
|
||
|
-- Abbau anwenden, aber nicht unter 0
|
||
|
local decayAmount = BAC_DECAY_RATE * minutesPassed
|
||
|
local currentBAC = math.max(0.0, playerBAC[citizenid].bac - decayAmount)
|
||
|
|
||
|
-- Cache mit abgebautem Wert aktualisieren
|
||
|
playerBAC[citizenid] = {
|
||
|
bac = currentBAC,
|
||
|
lastUpdated = currentTime
|
||
|
}
|
||
|
|
||
|
-- Datenbank mit neuem abgebautem Wert aktualisieren
|
||
|
MySQL.Async.execute('UPDATE player_bac SET bac_level = ?, last_updated = CURRENT_TIMESTAMP WHERE citizenid = ?',
|
||
|
{currentBAC, citizenid})
|
||
|
|
||
|
return currentBAC
|
||
|
else
|
||
|
-- Wenn nicht im Cache, aus Datenbank abrufen
|
||
|
local result = MySQL.Sync.fetchAll('SELECT bac_level, last_updated FROM player_bac WHERE citizenid = ?', {citizenid})
|
||
|
|
||
|
if result and result[1] then
|
||
|
local storedBAC = result[1].bac_level
|
||
|
local lastUpdated = result[1].last_updated
|
||
|
|
||
|
-- MySQL-Zeitstempel in Unix-Zeitstempel umwandeln
|
||
|
local pattern = "(%d+)-(%d+)-(%d+) (%d+):(%d+):(%d+)"
|
||
|
local year, month, day, hour, min, sec = lastUpdated:match(pattern)
|
||
|
local lastUpdateTime = os.time({year=year, month=month, day=day, hour=hour, min=min, sec=sec})
|
||
|
|
||
|
local currentTime = os.time()
|
||
|
local minutesPassed = (currentTime - lastUpdateTime) / 60
|
||
|
|
||
|
-- Abbau anwenden, aber nicht unter 0
|
||
|
local decayAmount = BAC_DECAY_RATE * minutesPassed
|
||
|
local currentBAC = math.max(0.0, storedBAC - decayAmount)
|
||
|
|
||
|
-- Cache aktualisieren
|
||
|
playerBAC[citizenid] = {
|
||
|
bac = currentBAC,
|
||
|
lastUpdated = currentTime
|
||
|
}
|
||
|
|
||
|
-- Datenbank mit neuem abgebautem Wert aktualisieren
|
||
|
MySQL.Async.execute('UPDATE player_bac SET bac_level = ?, last_updated = CURRENT_TIMESTAMP WHERE citizenid = ?',
|
||
|
{currentBAC, citizenid})
|
||
|
|
||
|
return currentBAC
|
||
|
else
|
||
|
-- Kein Eintrag gefunden, mit 0 initialisieren
|
||
|
playerBAC[citizenid] = {
|
||
|
bac = 0.0,
|
||
|
lastUpdated = os.time()
|
||
|
}
|
||
|
|
||
|
return 0.0
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Anbindung an das Konsumsystem
|
||
|
-- Dieses Event sollte ausgelöst werden, wenn ein Spieler ein alkoholisches Item konsumiert
|
||
|
RegisterNetEvent('qb-alcoholtest:server:alcoholConsumed')
|
||
|
AddEventHandler('qb-alcoholtest:server:alcoholConsumed', function(itemName, intensity)
|
||
|
local src = source
|
||
|
local Player = QBCore.Functions.GetPlayer(src)
|
||
|
|
||
|
if not Player then return end
|
||
|
|
||
|
local citizenid = Player.PlayerData.citizenid
|
||
|
local alcoholContent = 0.0
|
||
|
|
||
|
-- Prüfen, ob das konsumierte Item alkoholisch ist
|
||
|
if Config.AlcoholItems[itemName] then
|
||
|
alcoholContent = Config.AlcoholItems[itemName]
|
||
|
|
||
|
-- Basierend auf Intensität anpassen, falls angegeben
|
||
|
if intensity then
|
||
|
alcoholContent = alcoholContent * intensity
|
||
|
end
|
||
|
|
||
|
-- BAC des Spielers aktualisieren
|
||
|
UpdatePlayerBAC(citizenid, alcoholContent)
|
||
|
|
||
|
-- Spieler benachrichtigen
|
||
|
if Config.Debug then
|
||
|
TriggerClientEvent('QBCore:Notify', src, 'Du spürst die Wirkung des Alkohols.', 'primary')
|
||
|
end
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
-- Verwendbares Alkoholtester-Item erstellen
|
||
|
QBCore.Functions.CreateUseableItem('breathalyzer', function(source, item)
|
||
|
local src = source
|
||
|
TriggerClientEvent('qb-alcoholtest:client:useBreathalyzer', src)
|
||
|
end)
|
||
|
|
||
|
-- Alkoholtester-Events
|
||
|
RegisterServerEvent('qb-alcoholtest:server:doBacTest')
|
||
|
AddEventHandler('qb-alcoholtest:server:doBacTest', function(target)
|
||
|
TriggerClientEvent('qb-alcoholtest:client:requestBac', target, source, target)
|
||
|
end)
|
||
|
|
||
|
RegisterServerEvent('qb-alcoholtest:server:refusedBac')
|
||
|
AddEventHandler('qb-alcoholtest:server:refusedBac', function(leo, target)
|
||
|
TriggerClientEvent('qb-alcoholtest:client:bacRefused', leo, target)
|
||
|
end)
|
||
|
|
||
|
RegisterServerEvent('qb-alcoholtest:server:acceptedBac')
|
||
|
AddEventHandler('qb-alcoholtest:server:acceptedBac', function(leo, target)
|
||
|
TriggerClientEvent('qb-alcoholtest:client:acceptedBac', leo, target)
|
||
|
end)
|
||
|
|
||
|
-- Neues Event, um den tatsächlichen BAC-Wert aus dem System zu erhalten
|
||
|
RegisterServerEvent('qb-alcoholtest:server:getActualBAC')
|
||
|
AddEventHandler('qb-alcoholtest:server:getActualBAC', function(leo, target)
|
||
|
local targetPlayer = QBCore.Functions.GetPlayer(target)
|
||
|
|
||
|
if not targetPlayer then return end
|
||
|
|
||
|
local citizenid = targetPlayer.PlayerData.citizenid
|
||
|
local currentBAC = GetCurrentBAC(citizenid)
|
||
|
|
||
|
-- BAC auf 2 Dezimalstellen formatieren
|
||
|
local formattedBAC = string.format("%.2f", currentBAC)
|
||
|
|
||
|
-- Farbe basierend auf gesetzlichem Limit bestimmen
|
||
|
local color = '--color-black'
|
||
|
if currentBAC > Config.LegalLimit then
|
||
|
color = '--color-red'
|
||
|
end
|
||
|
|
||
|
-- BAC-Ergebnis an den Beamten senden
|
||
|
TriggerClientEvent('qb-alcoholtest:client:displayBac', leo, formattedBAC, color)
|
||
|
end)
|
||
|
|
||
|
-- Öffentliche Funktion für andere Ressourcen
|
||
|
exports('GetPlayerBAC', function(citizenid)
|
||
|
return GetCurrentBAC(citizenid)
|
||
|
end)
|
||
|
|
||
|
-- Öffentliche Funktion zum Aktualisieren des BAC-Werts
|
||
|
exports('UpdatePlayerBAC', function(citizenid, amount)
|
||
|
UpdatePlayerBAC(citizenid, amount)
|
||
|
end)
|
||
|
|
||
|
-- Sicherstellen, dass die Datenbanktabelle existiert, wenn die Ressource startet
|
||
|
MySQL.ready(function()
|
||
|
MySQL.Async.execute([[
|
||
|
CREATE TABLE IF NOT EXISTS `player_bac` (
|
||
|
`citizenid` varchar(50) NOT NULL,
|
||
|
`bac_level` float NOT NULL DEFAULT 0.0,
|
||
|
`last_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
|
PRIMARY KEY (`citizenid`)
|
||
|
);
|
||
|
]])
|
||
|
end)
|