Merge branch 'main' into main

This commit is contained in:
Nick Reagan
2025-01-29 20:04:47 -05:00
committed by GitHub
15 changed files with 510 additions and 107 deletions
+10 -3
View File
@@ -164,7 +164,7 @@ RegisterNetEvent('QBCore:Client:VehicleInfo', function(info)
local hasKeys = true
if GetResourceState('qb-vehiclekeys') == 'started' then
hasKeys = exports['qb-vehiclekeys']:HasKeys()
hasKeys = exports['qb-vehiclekeys']:HasKeys(plate)
end
local data = {
@@ -208,7 +208,9 @@ end)
-- Client Callback
RegisterNetEvent('QBCore:Client:TriggerClientCallback', function(name, ...)
QBCore.Functions.TriggerClientCallback(name, function(...)
if not QBCore.ClientCallbacks[name] then return end
QBCore.ClientCallbacks[name](function(...)
TriggerServerEvent('QBCore:Server:TriggerClientCallback', name, ...)
end, ...)
end)
@@ -216,7 +218,12 @@ end)
-- Server Callback
RegisterNetEvent('QBCore:Client:TriggerCallback', function(name, ...)
if QBCore.ServerCallbacks[name] then
QBCore.ServerCallbacks[name](...)
QBCore.ServerCallbacks[name].promise:resolve(...)
if QBCore.ServerCallbacks[name].callback then
QBCore.ServerCallbacks[name].callback(...)
end
QBCore.ServerCallbacks[name] = nil
end
end)
+43 -18
View File
@@ -6,14 +6,26 @@ function QBCore.Functions.CreateClientCallback(name, cb)
QBCore.ClientCallbacks[name] = cb
end
function QBCore.Functions.TriggerClientCallback(name, cb, ...)
if not QBCore.ClientCallbacks[name] then return end
QBCore.ClientCallbacks[name](cb, ...)
end
function QBCore.Functions.TriggerCallback(name, ...)
local cb = nil
local args = { ... }
function QBCore.Functions.TriggerCallback(name, cb, ...)
QBCore.ServerCallbacks[name] = cb
TriggerServerEvent('QBCore:Server:TriggerCallback', name, ...)
if QBCore.Shared.IsFunction(args[1]) then
cb = args[1]
table.remove(args, 1)
end
QBCore.ServerCallbacks[name] = {
callback = cb,
promise = promise.new()
}
TriggerServerEvent('QBCore:Server:TriggerCallback', name, table.unpack(args))
if cb == nil then
Citizen.Await(QBCore.ServerCallbacks[name].promise)
return QBCore.ServerCallbacks[name].promise.value
end
end
function QBCore.Debug(resource, obj, depth)
@@ -36,6 +48,13 @@ function QBCore.Functions.HasItem(items, amount)
return exports['qb-inventory']:HasItem(items, amount)
end
---Returns the full character name
---@return string
function QBCore.Functions.GetName()
local charinfo = QBCore.PlayerData.charinfo
return charinfo.firstname .. ' ' .. charinfo.lastname
end
---@param entity number - The entity to look at
---@param timeout number - The time in milliseconds before the function times out
---@param speed number - The speed at which the entity should turn
@@ -43,16 +62,13 @@ end
function QBCore.Functions.LookAtEntity(entity, timeout, speed)
local involved = GetInvokingResource()
if not DoesEntityExist(entity) then
turnPromise:reject(involved .. ' :^1 Entity does not exist')
return turnPromise.value
return involved .. ' :^1 Entity does not exist'
end
if not type(entity) == 'number' then
turnPromise:reject(involved .. ' :^1 Entity must be a number')
return turnPromise.value
if type(entity) ~= 'number' then
return involved .. ' :^1 Entity must be a number'
end
if not type(speed) == 'number' then
turnPromise:reject(involved .. ' :^1 Speed must be a number')
return turnPromise.value
if type(speed) ~= 'number' then
return involved .. ' :^1 Speed must be a number'
end
if speed > 5.0 then speed = 5.0 end
if timeout > 5000 then timeout = 5000 end
@@ -62,7 +78,7 @@ function QBCore.Functions.LookAtEntity(entity, timeout, speed)
local dx = targetPos.x - playerPos.x
local dy = targetPos.y - playerPos.y
local targetHeading = GetHeadingFromVector_2d(dx, dy)
local turnSpeed = speed
local turnSpeed
local startTimeout = GetGameTimer()
while true do
local currentHeading = GetEntityHeading(ped)
@@ -569,7 +585,7 @@ function QBCore.Functions.SetVehicleProperties(vehicle, props)
SetVehicleEngineHealth(vehicle, props.engineHealth + 0.0)
end
if props.tankHealth then
SetVehiclePetrolTankHealth(vehicle, props.tankHealth)
SetVehiclePetrolTankHealth(vehicle, props.tankHealth + 0.0)
end
if props.fuelLevel then
SetVehicleFuelLevel(vehicle, props.fuelLevel + 0.0)
@@ -578,7 +594,7 @@ function QBCore.Functions.SetVehicleProperties(vehicle, props)
SetVehicleDirtLevel(vehicle, props.dirtLevel + 0.0)
end
if props.oilLevel then
SetVehicleOilLevel(vehicle, props.oilLevel)
SetVehicleOilLevel(vehicle, props.oilLevel + 0.0)
end
if props.color1 then
if type(props.color1) == 'number' then
@@ -1078,3 +1094,12 @@ function QBCore.Functions.GetGroundHash(entity)
local retval, success, endCoords, surfaceNormal, materialHash, entityHit = GetShapeTestResultEx(num)
return materialHash, entityHit, surfaceNormal, endCoords, success, retval
end
for functionName, func in pairs(QBCore.Functions) do
if type(func) == 'function' then
exports(functionName, func)
end
end
-- Access a specific function directly:
-- exports['qb-core']:Notify('Hello Player!')
+42 -6
View File
@@ -5,10 +5,46 @@ QBCore.Shared = QBShared
QBCore.ClientCallbacks = {}
QBCore.ServerCallbacks = {}
exports('GetCoreObject', function()
return QBCore
end)
-- Get the full QBCore object (default behavior):
-- local QBCore = GetCoreObject()
-- To use this export in a script instead of manifest method
-- Just put this line of code below at the very top of the script
-- local QBCore = exports['qb-core']:GetCoreObject()
-- Get only specific parts of QBCore:
-- local QBCore = GetCoreObject({'Players', 'Config'})
local function GetCoreObject(filters)
if not filters then return QBCore end
local results = {}
for i = 1, #filters do
local key = filters[i]
if QBCore[key] then
results[key] = QBCore[key]
end
end
return results
end
exports('GetCoreObject', GetCoreObject)
local function GetSharedItems()
return QBShared.Items
end
exports('GetSharedItems', GetSharedItems)
local function GetSharedVehicles()
return QBShared.Vehicles
end
exports('GetSharedVehicles', GetSharedVehicles)
local function GetSharedWeapons()
return QBShared.Weapons
end
exports('GetSharedWeapons', GetSharedWeapons)
local function GetSharedJobs()
return QBShared.Jobs
end
exports('GetSharedJobs', GetSharedJobs)
local function GetSharedGangs()
return QBShared.Gangs
end
exports('GetSharedGangs', GetSharedGangs)
+1
View File
@@ -8,6 +8,7 @@ QBConfig.StatusInterval = 5000 -- how often to check hu
QBConfig.Money = {}
QBConfig.Money.MoneyTypes = { cash = 500, bank = 5000, crypto = 0 } -- type = startamount - Add or remove money types for your server (for ex. blackmoney = 0), remember once added it will not be removed from the database!
QBConfig.Money.DontAllowMinus = { 'cash', 'crypto' } -- Money that is not allowed going in minus
QBConfig.Money.MinusLimit = -5000 -- The maximum amount you can be negative
QBConfig.Money.PayCheckTimeOut = 10 -- The time in minutes that it will give the paycheck
QBConfig.Money.PayCheckSociety = false -- If true paycheck will come from the society account that the player is employed at, requires qb-management
+1 -1
View File
@@ -3,7 +3,7 @@ game 'gta5'
lua54 'yes'
author 'Kakarot'
description 'Core resource for the framework, contains all the core functionality and features'
version '1.2.6'
version '1.3.0'
shared_scripts {
'config.lua',
+133
View File
@@ -0,0 +1,133 @@
local Translations = {
error = {
not_online = 'खिलाडी अनलाइन छैन',
wrong_format = 'गलत ढाँचा',
missing_args = 'सबै तर्कहरू प्रविष्ट गरिएको छैन (x, y, z)',
missing_args2 = 'सबै तर्कहरू पूरा गर्नुपर्छ!',
no_access = 'यस आदेशको लागि पहुँच छैन',
company_too_poor = 'तपाईंको नियोक्ता टाट पल्टेको छ',
item_not_exist = 'वस्तु अवस्थित छैन',
too_heavy = 'इन्वेन्टरी धेरै भरिएको छ',
location_not_exist = 'स्थान अवस्थित छैन',
duplicate_license = '[QBCORE] - दोहोरिएको रकस्टार लाइसेन्स भेटियो',
no_valid_license = '[QBCORE] - मान्य रकस्टार लाइसेन्स भेटिएन',
not_whitelisted = '[QBCORE] - तपाईं यस सर्भरको लागि सेतो सूचीमा हुनुहुन्न',
server_already_open = 'सर्भर पहिले नै खुल्ला छ',
server_already_closed = 'सर्भर पहिले नै बन्द छ',
no_permission = 'तपाईंलाई यसका लागि अनुमति छैन।',
no_waypoint = 'वेपॉइंट सेट गरिएको छैन।',
tp_error = 'टेलिपोर्ट गर्दा त्रुटि।',
ban_table_not_found = '[QBCORE] - डाटाबेसमा प्रतिबन्ध तालिका फेला पार्न सकेन। कृपया तपाईंले SQL फाइल सही रूपमा आयात गरेको सुनिश्चित गर्नुहोस्।',
connecting_database_error = '[QBCORE] - डाटाबेससँग जडान गर्दा त्रुटि भयो। कृपया SQL सर्भर चलिरहेको छ र server.cfg फाइलमा विवरणहरू सही छन् भन्ने सुनिश्चित गर्नुहोस्।',
connecting_database_timeout = '[QBCORE] - डाटाबेस जडानले समय समाप्त गर्यो। कृपया SQL सर्भर चलिरहेको छ र server.cfg फाइलमा विवरणहरू सही छन् भन्ने सुनिश्चित गर्नुहोस्।',
},
success = {
server_opened = 'सर्भर खोलियो',
server_closed = 'सर्भर बन्द भयो',
teleported_waypoint = 'वेपॉइंटमा टेलिपोर्ट भयो।',
},
info = {
received_paycheck = 'तपाईंले $%{value} को तलब प्राप्त गर्नुभयो',
job_info = 'काम: %{value} | ग्रेड: %{value2} | ड्युटी: %{value3}',
gang_info = 'ग्याङ: %{value} | ग्रेड: %{value2}',
on_duty = 'तपाईं अब ड्युटीमा हुनुहुन्छ!',
off_duty = 'तपाईं अब ड्युटीबाट बाहिर हुनुहुन्छ!',
checking_ban = 'नमस्ते %s। हामी तपाईं प्रतिबन्धित हुनुहुन्छ कि छैन जाँच गर्दैछौं।',
join_server = 'स्वागत छ %s {Server Name} मा।',
checking_whitelisted = 'नमस्ते %s। हामी तपाईंको अनुमतिहरू जाँच्दैछौं।',
exploit_banned = 'तपाईंलाई धोकाधडीको लागि प्रतिबन्ध लगाइएको छ। थप जानकारीका लागि हाम्रो डिस्कर्ड हेर्नुहोस्: %{discord}',
exploit_dropped = 'धोकाधडीको लागि तपाईंलाई निकालिएको छ',
},
command = {
tp = {
help = 'खिलाडी वा निर्देशांकमा टेलिपोर्ट गर्नुहोस् (केवल प्रशासक)',
params = {
x = { name = 'id/x', help = 'खिलाडीको ID वा X स्थिति' },
y = { name = 'y', help = 'Y स्थिति' },
z = { name = 'z', help = 'Z स्थिति' },
},
},
tpm = { help = 'मार्करमा टेलिपोर्ट गर्नुहोस् (केवल प्रशासक)' },
togglepvp = { help = 'सर्भरमा PVP सक्रिय/निष्क्रिय गर्नुहोस् (केवल प्रशासक)' },
addpermission = {
help = 'खिलाडीलाई अनुमति दिनुहोस् (केवल देवता)',
params = {
id = { name = 'id', help = 'खिलाडीको ID' },
permission = { name = 'permission', help = 'अनुमतिका स्तर' },
},
},
removepermission = {
help = 'खिलाडीबाट अनुमति हटाउनुहोस् (केवल देवता)',
params = {
id = { name = 'id', help = 'खिलाडीको ID' },
permission = { name = 'permission', help = 'अनुमतिका स्तर' },
},
},
openserver = { help = 'सबैलाई सर्भर खोल्नुहोस् (केवल प्रशासक)' },
closeserver = {
help = 'अनुमति बिना मानिसहरूलाई सर्भर बन्द गर्नुहोस् (केवल प्रशासक)',
params = {
reason = { name = 'reason', help = 'बन्द गर्ने कारण (वैकल्पिक)' },
},
},
car = {
help = 'सवारी साधन उत्पन्न गर्नुहोस् (केवल प्रशासक)',
params = {
model = { name = 'model', help = 'सवारी साधनको मोडल नाम' },
},
},
dv = { help = 'सवारी साधन मेटाउनुहोस् (केवल प्रशासक)' },
dvall = { help = 'सबै सवारी साधन मेटाउनुहोस् (केवल प्रशासक)' },
dvp = { help = 'सबै NPC मेटाउनुहोस् (केवल प्रशासक)' },
dvo = { help = 'सबै वस्तुहरू मेटाउनुहोस् (केवल प्रशासक)' },
givemoney = {
help = 'खिलाडीलाई पैसा दिनुहोस् (केवल प्रशासक)',
params = {
id = { name = 'id', help = 'खिलाडीको ID' },
moneytype = { name = 'moneytype', help = 'पैसाको प्रकार (नगद, बैंक, क्रिप्टो)' },
amount = { name = 'amount', help = 'पैसाको रकम' },
},
},
setmoney = {
help = 'खिलाडीको पैसा सेट गर्नुहोस् (केवल प्रशासक)',
params = {
id = { name = 'id', help = 'खिलाडीको ID' },
moneytype = { name = 'moneytype', help = 'पैसाको प्रकार (नगद, बैंक, क्रिप्टो)' },
amount = { name = 'amount', help = 'पैसाको रकम' },
},
},
job = { help = 'तपाईंको काम जाँच्नुहोस्' },
setjob = {
help = 'खिलाडीलाई काम दिनुहोस् (केवल प्रशासक)',
params = {
id = { name = 'id', help = 'खिलाडीको ID' },
job = { name = 'job', help = 'कामको नाम' },
grade = { name = 'grade', help = 'कामको स्तर' },
},
},
gang = { help = 'तपाईंको ग्याङ जाँच्नुहोस्' },
setgang = {
help = 'खिलाडीलाई ग्याङ दिनुहोस् (केवल प्रशासक)',
params = {
id = { name = 'id', help = 'खिलाडीको ID' },
gang = { name = 'gang', help = 'ग्याङको नाम' },
grade = { name = 'grade', help = 'ग्याङको स्तर' },
},
},
ooc = { help = 'OOC च्याट सन्देश' },
me = {
help = 'स्थानीय सन्देश देखाउनुहोस्',
params = {
message = { name = 'message', help = 'पठाउनको लागि सन्देश' }
},
},
},
}
if GetConvar('qb_locale', 'en') == 'np' then
Lang = Locale:new({
phrases = Translations,
warnOnMissing = true,
fallbackLang = Locale:new({ phrases = {}, warnOnMissing = true }) -- Fallback to empty locale if needed
})
end
+119 -20
View File
@@ -1,28 +1,127 @@
local Translations = {
error = {
not_online = 'Oyuncu çevrimiçi değil.',
wrong_format = 'Yanlış format.',
missing_args = 'Hiçbir argüman girilmedi. (x, y, z)',
missing_args2 = 'Tüm argümanlar doldurulmalıdır.',
no_access = 'Bu komuta erişimin yok.',
company_too_poor = 'Şirketin hiç parası yok.',
item_not_exist = 'Eşya mevcut değil.',
too_heavy = 'Envanter çok dolu',
duplicate_license = 'Aynı rockstar lisansı zaten şu an sunucuda!',
no_valid_license = 'Geçerli bir rockstar lisans bulunamadı.',
not_whitelisted = 'Bu sunucuda whitelistin yok.'
not_online = 'Oyuncu çevrimdışı',
wrong_format = 'Hatalı format',
missing_args = 'Tüm argümanlar girilmedi (x, y, z)',
missing_args2 = 'Tüm argümanlar doldurulmalıdır!',
no_access = 'Bu komut için erişiminiz yok',
company_too_poor = 'İşvereniniz iflas etti',
item_not_exist = 'Eşya mevcut değil',
too_heavy = 'Envanter çok dolu',
location_not_exist = 'Konum mevcut değil',
duplicate_license = '[QBCORE] - Aynı Rockstar Lisansı Bulundu',
no_valid_license = '[QBCORE] - Geçerli Rockstar Lisansı Bulunamadı',
not_whitelisted = '[QBCORE] - Bu sunucu için beyaz listedesiniz',
server_already_open = 'Sunucu zaten açık',
server_already_closed = 'Sunucu zaten kapalı',
no_permission = 'Bu işlem için yetkiniz yok...',
no_waypoint = 'Bir işaret noktası ayarlanmamış.',
tp_error = 'Taşınırken hata oluştu.',
ban_table_not_found = '[QBCORE] - Veritabanında yasaklılar tablosu bulunamadı. Lütfen SQL dosyasının doğru şekilde yüklendiğinden emin olun.',
connecting_database_error = '[QBCORE] - Veritabanına bağlanırken hata oluştu. SQL sunucusunun çalıştığından ve server.cfg dosyasındaki bilgilerin doğru olduğundan emin olun.',
connecting_database_timeout = '[QBCORE] - Veritabanı bağlantısı zaman aşımına uğradı. SQL sunucusunun çalıştığından ve server.cfg dosyasındaki bilgilerin doğru olduğundan emin olun.',
},
success = {
server_opened = 'Sunucu açıldı',
server_closed = 'Sunucu kapandı',
teleported_waypoint = 'İşaret noktasına taşındınız.',
},
success = {},
info = {
received_paycheck = '$%{value} tutarında bir maaş çeki aldın.',
job_info = 'İş: %{value} | Seviye: %{value2} | Görev: %{value3}',
received_paycheck = 'Maaşınızı $%{value} aldınız',
job_info = 'İş: %{value} | Seviye: %{value2} | Görevde: %{value3}',
gang_info = 'Çete: %{value} | Seviye: %{value2}',
on_duty = 'Mesaiye girdin.',
off_duty = 'Mesaiden çıktın.',
checking_ban = 'Merhaba %s. Banlı mısın diye kontrol ediyoruz.',
join_server = 'Merhaba %s. {Server Name} adlı sunucumuza hoş geldin.',
checking_whitelisted = 'Merhaba %s. Whitelist\'in var mı diye kontrol ediyoruz.'
}
on_duty = 'Artık görevdeyiniz!',
off_duty = 'Artık görev dışında oldunuz!',
checking_ban = 'Merhaba %s. Yasaklı olup olmadığınızı kontrol ediyoruz.',
join_server = 'Hoşgeldiniz %s, {Sunucu Adı}\'na.',
checking_whitelisted = 'Merhaba %s. İzin durumunuzu kontrol ediyoruz.',
exploit_banned = 'Hile yaptığınız için yasaklandınız. Daha fazla bilgi için Discord\'umuza göz atın: %{discord}',
exploit_dropped = 'Hile yapmaktan dolayı sunucudan atıldınız',
},
command = {
tp = {
help = 'Oyuncuya veya Koordinatlara TP (Sadece Admin)',
params = {
x = { name = 'id/x', help = 'Oyuncu ID\'si veya X konumu' },
y = { name = 'y', help = 'Y konumu' },
z = { name = 'z', help = 'Z konumu' },
},
},
tpm = { help = 'İşaret noktasına TP (Sadece Admin)' },
togglepvp = { help = 'Sunucuda PVP modunu aç/kapat (Sadece Admin)' },
addpermission = {
help = 'Oyuncuya Yetki Ver (Tanrı Yetkisi)',
params = {
id = { name = 'id', help = 'Oyuncu ID\'si' },
permission = { name = 'permission', help = 'Yetki seviyesi' },
},
},
removepermission = {
help = 'Oyuncudan Yetki Al (Tanrı Yetkisi)',
params = {
id = { name = 'id', help = 'Oyuncu ID\'si' },
permission = { name = 'permission', help = 'Yetki seviyesi' },
},
},
openserver = { help = 'Sunucuyu herkes için aç (Sadece Admin)' },
closeserver = {
help = 'Sunucuyu yetkisi olmayanlar için kapat (Sadece Admin)',
params = {
reason = { name = 'reason', help = 'Kapanma nedeni (isteğe bağlı)' },
},
},
car = {
help = 'Araç Spawn Et (Sadece Admin)',
params = {
model = { name = 'model', help = 'Araç model adı' },
},
},
dv = { help = 'Aracı Sil (Sadece Admin)' },
dvall = { help = 'Tüm Araçları Sil (Sadece Admin)' },
dvp = { help = 'Tüm Pedleri Sil (Sadece Admin)' },
dvo = { help = 'Tüm Objeleri Sil (Sadece Admin)' },
givemoney = {
help = 'Bir Oyuncuya Para Ver (Sadece Admin)',
params = {
id = { name = 'id', help = 'Oyuncu ID\'si' },
moneytype = { name = 'moneytype', help = 'Para türü (nakit, banka, kripto)' },
amount = { name = 'amount', help = 'Verilecek para miktarı' },
},
},
setmoney = {
help = 'Oyuncunun Para Miktarını Ayarla (Sadece Admin)',
params = {
id = { name = 'id', help = 'Oyuncu ID\'si' },
moneytype = { name = 'moneytype', help = 'Para türü (nakit, banka, kripto)' },
amount = { name = 'amount', help = 'Para miktarı' },
},
},
job = { help = 'İşinizi Kontrol Edin' },
setjob = {
help = 'Bir Oyuncunun İşini Ayarla (Sadece Admin)',
params = {
id = { name = 'id', help = 'Oyuncu ID\'si' },
job = { name = 'job', help = 'İş adı' },
grade = { name = 'grade', help = 'İş seviyesi' },
},
},
gang = { help = 'Çetenizi Kontrol Edin' },
setgang = {
help = 'Bir Oyuncunun Çetesini Ayarla (Sadece Admin)',
params = {
id = { name = 'id', help = 'Oyuncu ID\'si' },
gang = { name = 'gang', help = 'Çete adı' },
grade = { name = 'grade', help = 'Çete seviyesi' },
},
},
ooc = { help = 'OOC Sohbet Mesajı' },
me = {
help = 'Yerel mesaj gönder',
params = {
message = { name = 'message', help = 'Gönderilecek mesaj' }
},
},
},
}
if GetConvar('qb_locale', 'en') == 'tr' then
+2 -1
View File
@@ -104,8 +104,9 @@ QBCore.Commands.Add('tp', Lang:t('command.tp.help'), { { name = Lang:t('command.
local x = tonumber((args[1]:gsub(',', ''))) + .0
local y = tonumber((args[2]:gsub(',', ''))) + .0
local z = tonumber((args[3]:gsub(',', ''))) + .0
local heading = args[4] and tonumber((args[4]:gsub(',', ''))) + .0 or false
if x ~= 0 and y ~= 0 and z ~= 0 then
TriggerClientEvent('QBCore:Command:TeleportToCoords', source, x, y, z)
TriggerClientEvent('QBCore:Command:TeleportToCoords', source, x, y, z, heading)
else
TriggerClientEvent('QBCore:Notify', source, Lang:t('error.wrong_format'), 'error')
end
+19 -3
View File
@@ -18,13 +18,21 @@ AddEventHandler('playerDropped', function(reason)
QBCore.Players[src] = nil
end)
AddEventHandler("onResourceStop", function(resName)
for i,v in pairs(QBCore.UsableItems) do
if v.resource == resName then
QBCore.UsableItems[i] = nil
end
end
end)
-- Player Connecting
local readyFunction = MySQL.ready
local databaseConnected, bansTableExists = readyFunction == nil, readyFunction == nil
if readyFunction ~= nil then
MySQL.ready(function()
databaseConnected = true
local DatabaseInfo = QBCore.Functions.GetDatabaseInfo()
if not DatabaseInfo or not DatabaseInfo.exists then return end
@@ -117,15 +125,23 @@ end)
-- Client Callback
RegisterNetEvent('QBCore:Server:TriggerClientCallback', function(name, ...)
if QBCore.ClientCallbacks[name] then
QBCore.ClientCallbacks[name](...)
QBCore.ClientCallbacks[name].promise:resolve(...)
if QBCore.ClientCallbacks[name].callback then
QBCore.ClientCallbacks[name].callback(...)
end
QBCore.ClientCallbacks[name] = nil
end
end)
-- Server Callback
RegisterNetEvent('QBCore:Server:TriggerCallback', function(name, ...)
if not QBCore.ServerCallbacks[name] then return end
local src = source
QBCore.Functions.TriggerCallback(name, src, function(...)
QBCore.ServerCallbacks[name](src, function(...)
TriggerClientEvent('QBCore:Client:TriggerCallback', src, name, ...)
end, ...)
end)
+74 -42
View File
@@ -394,33 +394,30 @@ function QBCore.Functions.CreateVehicle(source, model, vehtype, coords, warp)
return veh
end
---Paychecks (standalone - don't touch)
function PaycheckInterval()
if next(QBCore.Players) then
for _, Player in pairs(QBCore.Players) do
if Player 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['qb-banking']:GetAccountBalance(Player.PlayerData.job.name)
if account ~= 0 then -- Checks if player is employed by a society
if account < payment then -- Checks if company has enough money to pay society
TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('error.company_too_poor'), 'error')
else
Player.Functions.AddMoney('bank', payment, 'paycheck')
exports['qb-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
if not next(QBCore.Players) then return end
for _, Player in pairs(QBCore.Players) do
if not Player then return end
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['qb-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['qb-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
@@ -434,9 +431,26 @@ end
---@param source any
---@param cb function
---@param ... any
function QBCore.Functions.TriggerClientCallback(name, source, cb, ...)
QBCore.ClientCallbacks[name] = cb
TriggerClientEvent('QBCore:Client:TriggerClientCallback', source, name, ...)
function QBCore.Functions.TriggerClientCallback(name, source, ...)
local cb = nil
local args = { ... }
if QBCore.Shared.IsFunction(args[1]) then
cb = args[1]
table.remove(args, 1)
end
QBCore.ClientCallbacks[name] = {
callback = cb,
promise = promise.new()
}
TriggerClientEvent('QBCore:Client:TriggerClientCallback', source, name, table.unpack(args))
if cb == nil then
Citizen.Await(QBCore.ClientCallbacks[name].promise)
return QBCore.ClientCallbacks[name].promise.value
end
end
---Create Server Callback
@@ -446,23 +460,32 @@ function QBCore.Functions.CreateCallback(name, cb)
QBCore.ServerCallbacks[name] = cb
end
---Trigger Serv er Callback
---@param name string
---@param source any
---@param cb function
---@param ... any
function QBCore.Functions.TriggerCallback(name, source, cb, ...)
if not QBCore.ServerCallbacks[name] then return end
QBCore.ServerCallbacks[name](source, cb, ...)
end
-- Items
---Create a usable item
---@param item string
---@param data function
function QBCore.Functions.CreateUseableItem(item, data)
QBCore.UsableItems[item] = data
local rawFunc = nil
if type(data) == 'table' then
if rawget(data, '__cfx_functionReference') then
rawFunc = data
elseif data.cb and rawget(data.cb, '__cfx_functionReference') then
rawFunc = data.cb
elseif data.callback and rawget(data.callback, '__cfx_functionReference') then
rawFunc = data.callback
end
elseif type(data) == 'function' then
rawFunc = data
end
if rawFunc then
QBCore.UsableItems[item] = {
func = rawFunc,
resource = GetInvokingResource()
}
end
end
---Checks if the given item is usable
@@ -628,23 +651,23 @@ end
function QBCore.Functions.GetDatabaseInfo()
local details = {
exists = false,
database = "",
database = '',
}
local connectionString = GetConvar("mysql_connection_string", "")
local connectionString = GetConvar('mysql_connection_string', '')
if connectionString == "" then
if connectionString == '' then
return details
elseif connectionString:find("mysql://") then
elseif connectionString:find('mysql://') then
connectionString = connectionString:sub(9, -1)
details.database = connectionString:sub(connectionString:find("/") + 1, -1):gsub("[%?]+[%w%p]*$", "")
details.database = connectionString:sub(connectionString:find('/') + 1, -1):gsub('[%?]+[%w%p]*$', '')
details.exists = true
return details
else
connectionString = { string.strsplit(";", connectionString) }
connectionString = { string.strsplit(';', connectionString) }
for i = 1, #connectionString do
local v = connectionString[i]
if v:match("database") then
if v:match('database') then
details.database = v:sub(10, #v)
details.exists = true
return details
@@ -702,3 +725,12 @@ function QBCore.Functions.PrepForSQL(source, data, pattern)
end
return true
end
for functionName, func in pairs(QBCore.Functions) do
if type(func) == 'function' then
exports(functionName, func)
end
end
-- Access a specific function directly:
-- exports['qb-core']:Notify(source, 'Hello Player!')
+42 -6
View File
@@ -4,10 +4,46 @@ QBCore.Shared = QBShared
QBCore.ClientCallbacks = {}
QBCore.ServerCallbacks = {}
exports('GetCoreObject', function()
return QBCore
end)
-- Get the full QBCore object (default behavior):
-- local QBCore = GetCoreObject()
-- To use this export in a script instead of manifest method
-- Just put this line of code below at the very top of the script
-- local QBCore = exports['qb-core']:GetCoreObject()
-- Get only specific parts of QBCore:
-- local QBCore = GetCoreObject({'Players', 'Config'})
local function GetCoreObject(filters)
if not filters then return QBCore end
local results = {}
for i = 1, #filters do
local key = filters[i]
if QBCore[key] then
results[key] = QBCore[key]
end
end
return results
end
exports('GetCoreObject', GetCoreObject)
local function GetSharedItems()
return QBShared.Items
end
exports('GetSharedItems', GetSharedItems)
local function GetSharedVehicles()
return QBShared.Vehicles
end
exports('GetSharedVehicles', GetSharedVehicles)
local function GetSharedWeapons()
return QBShared.Weapons
end
exports('GetSharedWeapons', GetSharedWeapons)
local function GetSharedJobs()
return QBShared.Jobs
end
exports('GetSharedJobs', GetSharedJobs)
local function GetSharedGangs()
return QBShared.Gangs
end
exports('GetSharedGangs', GetSharedGangs)
+6
View File
@@ -253,6 +253,11 @@ function QBCore.Player.CreatePlayer(PlayerData, Offline)
return QBCore.Functions.HasItem(self.PlayerData.source, items, amount)
end
function self.Functions.GetName()
local charinfo = self.PlayerData.charinfo
return charinfo.firstname .. ' ' .. charinfo.lastname
end
function self.Functions.SetJobDuty(onDuty)
self.PlayerData.job.onduty = not not onDuty
TriggerEvent('QBCore:Server:OnJobUpdate', self.PlayerData.source, self.PlayerData.job)
@@ -341,6 +346,7 @@ function QBCore.Player.CreatePlayer(PlayerData, Offline)
end
end
end
if self.PlayerData.money[moneytype] - amount < QBCore.Config.Money.MinusLimit then return false end
self.PlayerData.money[moneytype] = self.PlayerData.money[moneytype] - amount
if not self.Offline then
+6 -6
View File
@@ -50,13 +50,13 @@ QBShared.Items = {
weapon_pistolxm3 = { name = 'weapon_pistolxm3', label = 'Pistol XM3', weight = 1000, type = 'weapon', ammotype = 'AMMO_PISTOL', image = 'weapon_pistolxm3.png', unique = true, useable = true, description = 'Pistol XM3' },
-- Submachine Guns
weapon_microsmg = { name = 'weapon_microsmg', label = 'Micro SMG', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_microsmg.png', unique = true, useable = false, description = 'A handheld light weight machine gun' },
weapon_smg = { name = 'weapon_smg', label = 'SMG', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_smg.png', unique = true, useable = false, description = 'A handheld light weight machine gun' },
weapon_microsmg = { name = 'weapon_microsmg', label = 'Micro SMG', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_microsmg.png', unique = true, useable = false, description = 'A handheld light weight machine gun' },
weapon_smg = { name = 'weapon_smg', label = 'SMG', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_smg.png', unique = true, useable = false, description = 'A handheld light weight machine gun' },
weapon_smg_mk2 = { name = 'weapon_smg_mk2', label = 'SMG Mk II', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_smg_mk2.png', unique = true, useable = true, description = 'SMG MK2' },
weapon_assaultsmg = { name = 'weapon_assaultsmg', label = 'Assault SMG', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_assaultsmg.png', unique = true, useable = false, description = 'An assault version of a handheld light weight machine gun' },
weapon_combatpdw = { name = 'weapon_combatpdw', label = 'Combat PDW', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_combatpdw.png', unique = true, useable = false, description = 'A combat version of a handheld light weight machine gun' },
weapon_assaultsmg = { name = 'weapon_assaultsmg', label = 'Assault SMG', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_assaultsmg.png', unique = true, useable = false, description = 'An assault version of a handheld light weight machine gun' },
weapon_combatpdw = { name = 'weapon_combatpdw', label = 'Combat PDW', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_combatpdw.png', unique = true, useable = false, description = 'A combat version of a handheld light weight machine gun' },
weapon_machinepistol = { name = 'weapon_machinepistol', label = 'Tec-9', weight = 1000, type = 'weapon', ammotype = 'AMMO_PISTOL', image = 'weapon_machinepistol.png', unique = true, useable = false, description = 'A self-loading pistol capable of burst or fully automatic fire' },
weapon_minismg = { name = 'weapon_minismg', label = 'Mini SMG', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_minismg.png', unique = true, useable = false, description = 'A mini handheld light weight machine gun' },
weapon_minismg = { name = 'weapon_minismg', label = 'Mini SMG', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_minismg.png', unique = true, useable = false, description = 'A mini handheld light weight machine gun' },
weapon_raycarbine = { name = 'weapon_raycarbine', label = 'Unholy Hellbringer', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_raycarbine.png', unique = true, useable = true, description = 'Weapon Raycarbine' },
-- Shotguns
@@ -74,7 +74,7 @@ QBShared.Items = {
-- Assault Rifles
weapon_assaultrifle = { name = 'weapon_assaultrifle', label = 'Assault Rifle', weight = 1000, type = 'weapon', ammotype = 'AMMO_RIFLE', image = 'weapon_assaultrifle.png', unique = true, useable = false, description = 'A rapid-fire, magazine-fed automatic rifle designed for infantry use' },
weapon_assaultrifle_mk2 = { name = 'weapon_assaultrifle_mk2', label = 'Assault Rifle Mk II', weight = 1000, type = 'weapon', ammotype = 'AMMO_RIFLE', image = 'weapon_assaultrifle_mk2.png', unique = true, useable = true, description = 'Assault Rifle MK2' },
weapon_carbinerifle = { name = 'weapon_carbinerifle', label = 'Carbine Rifle', weight = 1000, type = 'weapon', ammotype = 'AMMO_RIFLE', image = 'weapon_carbinerifle.png', unique = true, useable = false, description = 'A light weight automatic rifle' },
weapon_carbinerifle = { name = 'weapon_carbinerifle', label = 'Carbine Rifle', weight = 1000, type = 'weapon', ammotype = 'AMMO_RIFLE', image = 'weapon_carbinerifle.png', unique = true, useable = false, description = 'A light weight automatic rifle' },
weapon_carbinerifle_mk2 = { name = 'weapon_carbinerifle_mk2', label = 'Carbine Rifle Mk II', weight = 1000, type = 'weapon', ammotype = 'AMMO_RIFLE', image = 'weapon_carbinerifle_mk2.png', unique = true, useable = true, description = 'Carbine Rifle MK2' },
weapon_advancedrifle = { name = 'weapon_advancedrifle', label = 'Advanced Rifle', weight = 1000, type = 'weapon', ammotype = 'AMMO_RIFLE', image = 'weapon_advancedrifle.png', unique = true, useable = false, description = 'An assault version of a rapid-fire, magazine-fed automatic rifle designed for infantry use' },
weapon_specialcarbine = { name = 'weapon_specialcarbine', label = 'Special Carbine', weight = 1000, type = 'weapon', ammotype = 'AMMO_RIFLE', image = 'weapon_specialcarbine.png', unique = true, useable = false, description = 'An extremely versatile assault rifle for any combat situation' },
+8
View File
@@ -68,6 +68,14 @@ function QBShared.ChangeVehicleExtra(vehicle, extra, enable)
end
end
function QBShared.IsFunction(value)
if type(value) == 'table' then
return value.__cfx_functionReference ~= nil and type(value.__cfx_functionReference) == "string"
end
return type(value) == 'function'
end
function QBShared.SetDefaultVehicleExtras(vehicle, config)
-- Clear Extras
for i = 1, 20 do
+4 -1
View File
@@ -765,7 +765,9 @@ local Vehicles = {
{ model = 'formula', name = 'PR4', brand = 'Progen', price = 100000, category = 'openwheel', type = 'automobile', shop = 'none' },
}
QBShared.VehicleHashes = QBShared.VehicleHashes or {}
for i = 1, #Vehicles do
local hash = joaat(Vehicles[i].model)
QBShared.Vehicles[Vehicles[i].model] = {
spawncode = Vehicles[i].model,
name = Vehicles[i].name,
@@ -773,8 +775,9 @@ for i = 1, #Vehicles do
model = Vehicles[i].model,
price = Vehicles[i].price,
category = Vehicles[i].category,
hash = joaat(Vehicles[i].model),
hash = hash,
type = Vehicles[i].type,
shop = Vehicles[i].shop
}
QBShared.VehicleHashes[hash] = QBShared.Vehicles[Vehicles[i].model]
end