diff --git a/client/events.lua b/client/events.lua index c172c16..f08e019 100644 --- a/client/events.lua +++ b/client/events.lua @@ -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) diff --git a/client/functions.lua b/client/functions.lua index 45034a5..f6bca00 100644 --- a/client/functions.lua +++ b/client/functions.lua @@ -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 @@ -1075,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!') diff --git a/client/main.lua b/client/main.lua index 7407a6d..05d3b68 100644 --- a/client/main.lua +++ b/client/main.lua @@ -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) diff --git a/fxmanifest.lua b/fxmanifest.lua index bc0da07..924a561 100644 --- a/fxmanifest.lua +++ b/fxmanifest.lua @@ -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', diff --git a/locale/tr.lua b/locale/tr.lua index 9acc97e..d123721 100644 --- a/locale/tr.lua +++ b/locale/tr.lua @@ -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 diff --git a/server/commands.lua b/server/commands.lua index 5f90980..368736f 100644 --- a/server/commands.lua +++ b/server/commands.lua @@ -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 diff --git a/server/events.lua b/server/events.lua index 9311e80..00b0fa5 100644 --- a/server/events.lua +++ b/server/events.lua @@ -32,7 +32,7 @@ local databaseConnected, bansTableExists = readyFunction == nil, readyFunction = if readyFunction ~= nil then MySQL.ready(function() databaseConnected = true - + local DatabaseInfo = QBCore.Functions.GetDatabaseInfo() if not DatabaseInfo or not DatabaseInfo.exists then return end @@ -125,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) diff --git a/server/functions.lua b/server/functions.lua index 9cfe78e..8f81093 100644 --- a/server/functions.lua +++ b/server/functions.lua @@ -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,16 +460,6 @@ 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 @@ -464,7 +468,7 @@ end function QBCore.Functions.CreateUseableItem(item, data) local rawFunc = nil - if type(data) == "table" then + if type(data) == 'table' then if rawget(data, '__cfx_functionReference') then rawFunc = data elseif data.cb and rawget(data.cb, '__cfx_functionReference') then @@ -472,10 +476,10 @@ function QBCore.Functions.CreateUseableItem(item, data) elseif data.callback and rawget(data.callback, '__cfx_functionReference') then rawFunc = data.callback end - elseif type(data) == "function" then + elseif type(data) == 'function' then rawFunc = data end - + if rawFunc then QBCore.UsableItems[item] = { func = rawFunc, @@ -647,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 @@ -721,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!') diff --git a/server/main.lua b/server/main.lua index 368dc05..d6228e5 100644 --- a/server/main.lua +++ b/server/main.lua @@ -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) diff --git a/server/player.lua b/server/player.lua index cbc5032..4f73c0d 100644 --- a/server/player.lua +++ b/server/player.lua @@ -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) diff --git a/shared/items.lua b/shared/items.lua index b6f93a8..84de923 100644 --- a/shared/items.lua +++ b/shared/items.lua @@ -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' }, diff --git a/shared/main.lua b/shared/main.lua index d01b93c..2863b35 100644 --- a/shared/main.lua +++ b/shared/main.lua @@ -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 diff --git a/shared/vehicles.lua b/shared/vehicles.lua index bf6bf87..b745c09 100644 --- a/shared/vehicles.lua +++ b/shared/vehicles.lua @@ -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