Merge branch 'main' into perf

This commit is contained in:
Mycroft
2022-02-07 15:46:06 +00:00
committed by GitHub
224 changed files with 3074 additions and 3494 deletions
+3
View File
@@ -0,0 +1,3 @@
[submodule "[esx_addons]/esx_multicharacter"]
path = [esx_addons]/esx_multicharacter
url = https://github.com/thelindat/esx_multicharacter.git
+2 -2
View File
@@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
esx-legacy
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
esx-legacy Copyright (C) 2015-2021 Jérémie N'gadi
esx-legacy Copyright (C) 2015-2022 Jérémie N'gadi
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
+3 -76
View File
@@ -1,7 +1,7 @@
<h1 align='center'>ESX Legacy</a></h1><p align='center'><b><a href='https://discord.gg/cNx6HF9P5J'>Development Discord</a> - <a href='https://esx-framework.org/'>Website</a> - <a href='https://discord.gg/J6VqFPwvVp'>Support Discord</a></b></h5>
<h1 align='center'>ESX Legacy</a></h1><p align='center'><b><a href='https://discord.gg/cNx6HF9P5J'>Discord</a> - <a href='https://esx-framework.org/'>Website</a> - <a href='https://docs.esx-framework.org/docs/legacy/installation'>Documentation</a></b></h5>
##### ESX is the most popular framework for creating economy-based roleplay servers on FiveM, with many official and community resources designed to utilise the tools provided here. For a taste of what's available:
##### ESX is the leading framework for creating roleplay servers on FiveM, with many official and community resources designed to utilise the tools provided here. For a taste of what's available:
> esx_identity: Enables character registration defining a players name, sex, height, and date of birth
> esx_society: Allows job resources to register a society, gaining employee management, society funds, and more
@@ -14,86 +14,13 @@
Many more resources are included in this repository, or you can browse the [ESX Community Github](https://github.com/esx-community/) or [Cfx.re Releases board](https://forum.cfx.re/tag/esx) for more.
### Information
##### Legacy provides some necessary bug-fixes and improvements to optimise the framework before reaching the end of official support by the development team.
##### Most resources designed for 1.2 will have no issues with Legacy, notable exceptions are those which modify spawning/loading behaviour. There are several minor feature updates which do not impact compatibility with old resources.
##### NOTE: The loadouts system in ESX has always been problematic, and fixing it would require a complete overhaul. Your best option is to use a resource that handles weapons as items.
#### Optimisation
- Utilise compile-time jenkins hashing over the GetHashKey native
- Update old MySQL queries to use MySQL.store to improve performance, especially during player saving
- Several loops will now sleep when their tasks are not necessary to perform
- Improved support when using ESX Identity to reduce events and queries during player login
- Support for the latest weapons and components
#### Features
- Integrated support for identity data
- Integrated commands from esx_adminplus
- All players will be saved immediately before a txAdmin scheduled restart
- Detect if a player is new and send the result to the playerLoaded event
- Support for players logging out when using multicharacter resources
- Cache the players ped id and death state in ESX.PlayerData
- Added an imports file (similar to locales.lua) for setting up events and functions in other resources
- Before defining all manifest script files, add `shared_script '@es_extended/imports.lua'`
- Automatically retrieve the ESX object, removing the need to send a callback event on both the client and server
- Ensures current information is always returned when using `ESX.PlayerData` (except loadout and inventory)
- Spawnmanager is being utilised to correctly handle player spawns
- Potential conflicts with some third-party resources that do not expect spawnmanager
- Added an improved function when performing xPlayer loops to prevent large server hitches
- Using `ESX.GetExtendedPlayers()` instead of `ESX.GetPlayers()`
- You can use arguments with the new function as well, such as
- ESX.GetExtendedPlayers('job', 'police')
- ESX.GetExtendedPlayers('group', 'admin')
#### Fixes
- ESX.Jobs table is populated after all jobs are setup, allowing other resources to retrieve it if needed
- All weapons are properly removed when using the clearloadout command
##### For creating or updating resources refer to the [updated boilerplate](/esx_example).
### 1.2 Features
- Weight based inventory system
- Weapons support, including support for attachments and tints
- Supports different money accounts (defaulted with cash, bank and black money)
- Many official resources available in our GitHub
- Job system, with grades and clothes support
- Supports multiple languages, most strings are localized
- Easy to use API for developers to easily integrate ESX to their projects
- Register your own commands easily, with argument validation, chat suggestion and using FXServer ACL
### Requirements
- All resources from the `core` folder
- [spawnmanager](https://github.com/citizenfx/cfx-server-data)
- [mysql-async](https://github.com/brouznouf/fivem-mysql-async/releases/tag/3.3.2)
### Installation
- Download files to the resources folder and, if desired, prepare directories for organisation (i.e. resources/[core]/es_extended)
- Import `es_extended.sql` in your database
- Import any other sql files for the resources you are using
- Ensure all resources config files have been adjusted for your preferences
- Use or refer to the included server.cfg for start order and settings
### Conflicts
* The following resources should not be used with ESX Legacy
- essentialmode
- basic-gamemode
- fivem-map-skater
- fivem-map-hipster
- default_spawnpoint
### Information
ESX was initially developed by Gizz back in 2017 for his friend as the were creating an FiveM server and there wasn't any economy roleplaying frameworks available. The original code was written within a week or two and later open sourced, it has ever since been improved and parts been rewritten to further improve on it.
- [ESX Documentation](https://esx-framework.github.io/es_extended/)
- [FiveM Native Reference](https://runtime.fivem.net/doc/reference.html)
### Legal
### License
es_extended - ESX framework for FiveM
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program Is free software: you can redistribute it And/Or modify it under the terms Of the GNU General Public License As published by the Free Software Foundation, either version 3 Of the License, Or (at your option) any later version.
+1198
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
async
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
async Copyright (C) 2015-2021 Jérémie N'gadi
async Copyright (C) 2015-2022 Jérémie N'gadi
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
+2 -2
View File
@@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
cron
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
cron Copyright (C) 2015-2021 Jérémie N'gadi
cron Copyright (C) 2015-2022 Jérémie N'gadi
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
+1 -1
View File
@@ -43,7 +43,7 @@ TriggerEvent('cron:runAt', 18, 30, CronTask)
### License
cron - do stuff in a specified time
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program Is free software: you can redistribute it And/Or modify it under the terms Of the GNU General Public License As published by the Free Software Foundation, either version 3 Of the License, Or (at your option) any later version.
+2 -2
View File
@@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
es_extended
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
es_extended Copyright (C) 2015-2021 Jérémie N'gadi
es_extended Copyright (C) 2015-2022 Jérémie N'gadi
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
-102
View File
@@ -1,102 +0,0 @@
<h1 align='center'>ESX Legacy</a></h1><p align='center'><b><a href='https://discord.gg/cNx6HF9P5J'>Development Discord</a> - <a href='https://esx-framework.org/'>Website</a> - <a href='https://discord.gg/J6VqFPwvVp'>Support Discord</a></b></h5>
##### ESX is the most popular framework for creating economy-based roleplay servers on FiveM, with many official and community resources designed to utilise the tools provided here. For a taste of what's available:
> esx_identity: Enables character registration defining a players name, sex, height, and date of birth
> esx_society: Allows job resources to register a society, gaining employee management, society funds, and more
> esx_billing: Allows members of some societies to send fines or bills to other players
> esx_vehicleshop: Allow players to purchase vehicles from a dealership, or setup society support for a player-managed dealership
> esx_ambulancejob: Adds a death and respawn system while allowing players to work as EMS to heal and revive others
Many more resources are included in this repository, or you can browse the [ESX Community Github](https://github.com/esx-community/) or [Cfx.re Releases board](https://forum.cfx.re/tag/esx) for more.
### Information
##### Legacy provides some necessary bug-fixes and improvements to optimise the framework before reaching the end of official support by the development team.
##### Most resources designed for 1.2 will have no issues with Legacy, notable exceptions are those which modify spawning/loading behaviour. There are several minor feature updates which do not impact compatibility with old resources.
##### NOTE: The loadouts system in ESX has always been problematic, and fixing it would require a complete overhaul. Your best option is to use a resource that handles weapons as items.
#### Optimisation
- Utilise compile-time jenkins hashing over the GetHashKey native
- Update old MySQL queries to use MySQL.store to improve performance, especially during player saving
- Several loops will now sleep when their tasks are not necessary to perform
- Improved support when using ESX Identity to reduce events and queries during player login
- Support for the latest weapons and components
#### Features
- Integrated support for identity data
- Integrated commands from esx_adminplus
- All players will be saved immediately before a txAdmin scheduled restart
- Detect if a player is new and send the result to the playerLoaded event
- Support for players logging out when using multicharacter resources
- Cache the players ped id and death state in ESX.PlayerData
- Added an imports file (similar to locales.lua) for setting up events and functions in other resources
- Before defining all manifest script files, add `shared_script '@es_extended/imports.lua'`
- Automatically retrieve the ESX object, removing the need to send a callback event on both the client and server
- Ensures current information is always returned when using `ESX.PlayerData` (except loadout and inventory)
- Spawnmanager is being utilised to correctly handle player spawns
- Potential conflicts with some third-party resources that do not expect spawnmanager
- Added an improved function when performing xPlayer loops to prevent large server hitches
- Using `ESX.GetExtendedPlayers()` instead of `ESX.GetPlayers()`
- You can use arguments with the new function as well, such as
- ESX.GetExtendedPlayers('job', 'police')
- ESX.GetExtendedPlayers('group', 'admin')
#### Fixes
- ESX.Jobs table is populated after all jobs are setup, allowing other resources to retrieve it if needed
- All weapons are properly removed when using the clearloadout command
##### For creating or updating resources refer to the [updated boilerplate](/esx_example).
### 1.2 Features
- Weight based inventory system
- Weapons support, including support for attachments and tints
- Supports different money accounts (defaulted with cash, bank and black money)
- Many official resources available in our GitHub
- Job system, with grades and clothes support
- Supports multiple languages, most strings are localized
- Easy to use API for developers to easily integrate ESX to their projects
- Register your own commands easily, with argument validation, chat suggestion and using FXServer ACL
### Requirements
- All resources from the `core` folder
- [spawnmanager](https://github.com/citizenfx/cfx-server-data)
- [mysql-async](https://github.com/brouznouf/fivem-mysql-async/releases/tag/3.3.2)
### Installation
- Download files to the resources folder and, if desired, prepare directories for organisation (i.e. resources/[core]/es_extended)
- Import `es_extended.sql` in your database
- Import any other sql files for the resources you are using
- Ensure all resources config files have been adjusted for your preferences
- Use or refer to the included server.cfg for start order and settings
### Conflicts
* The following resources should not be used with ESX Legacy
- essentialmode
- basic-gamemode
- fivem-map-skater
- fivem-map-hipster
- default_spawnpoint
### Information
ESX was initially developed by Gizz back in 2017 for his friend as the were creating an FiveM server and there wasn't any economy roleplaying frameworks available. The original code was written within a week or two and later open sourced, it has ever since been improved and parts been rewritten to further improve on it.
- [ESX Documentation](https://esx-framework.github.io/es_extended/)
- [FiveM Native Reference](https://runtime.fivem.net/doc/reference.html)
### Legal
### License
es_extended - ESX framework for FiveM
Copyright (C) 2015-2021 Jérémie N'gadi
This program Is free software: you can redistribute it And/Or modify it under the terms Of the GNU General Public License As published by the Free Software Foundation, either version 3 Of the License, Or (at your option) any later version.
This program Is distributed In the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty Of MERCHANTABILITY Or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License For more details.
You should have received a copy Of the GNU General Public License along with this program. If Not, see http://www.gnu.org/licenses/.
+2 -2
View File
@@ -2,6 +2,6 @@ AddEventHandler('esx:getSharedObject', function(cb)
cb(ESX)
end)
function getSharedObject()
exports('getSharedObject', function()
return ESX
end
end)
+19 -18
View File
@@ -1,9 +1,10 @@
ESX = {}
Core = {}
ESX.PlayerData = {}
ESX.PlayerLoaded = false
ESX.CurrentRequestId = 0
ESX.ServerCallbacks = {}
ESX.TimeoutCallbacks = {}
Core.CurrentRequestId = 0
Core.ServerCallbacks = {}
Core.TimeoutCallbacks = {}
ESX.UI = {}
ESX.UI.HUD = {}
@@ -21,15 +22,15 @@ ESX.Scaleform.Utils = {}
ESX.Streaming = {}
ESX.SetTimeout = function(msec, cb)
table.insert(ESX.TimeoutCallbacks, {
table.insert(Core.TimeoutCallbacks, {
time = GetGameTimer() + msec,
cb = cb
})
return #ESX.TimeoutCallbacks
return #Core.TimeoutCallbacks
end
ESX.ClearTimeout = function(i)
ESX.TimeoutCallbacks[i] = nil
Core.TimeoutCallbacks[i] = nil
end
ESX.IsPlayerLoaded = function()
@@ -86,14 +87,14 @@ ESX.ShowFloatingHelpNotification = function(msg, coords)
end
ESX.TriggerServerCallback = function(name, cb, ...)
ESX.ServerCallbacks[ESX.CurrentRequestId] = cb
Core.ServerCallbacks[Core.CurrentRequestId] = cb
TriggerServerEvent('esx:triggerServerCallback', name, ESX.CurrentRequestId, ...)
TriggerServerEvent('esx:triggerServerCallback', name, Core.CurrentRequestId, ...)
if ESX.CurrentRequestId < 65535 then
ESX.CurrentRequestId = ESX.CurrentRequestId + 1
if Core.CurrentRequestId < 65535 then
Core.CurrentRequestId = Core.CurrentRequestId + 1
else
ESX.CurrentRequestId = 0
Core.CurrentRequestId = 0
end
end
@@ -989,8 +990,8 @@ end
RegisterNetEvent('esx:serverCallback')
AddEventHandler('esx:serverCallback', function(requestId, ...)
ESX.ServerCallbacks[requestId](...)
ESX.ServerCallbacks[requestId] = nil
Core.ServerCallbacks[requestId](...)
Core.ServerCallbacks[requestId] = nil
end)
RegisterNetEvent('esx:showNotification')
@@ -1012,13 +1013,13 @@ end)
Citizen.CreateThread(function()
while true do
local sleep = 100
if #ESX.TimeoutCallbacks > 0 then
if #Core.TimeoutCallbacks > 0 then
local currTime = GetGameTimer()
sleep = 0
for i=1, #ESX.TimeoutCallbacks, 1 do
if currTime >= ESX.TimeoutCallbacks[i].time then
ESX.TimeoutCallbacks[i].cb()
ESX.TimeoutCallbacks[i] = nil
for i=1, #Core.TimeoutCallbacks, 1 do
if currTime >= Core.TimeoutCallbacks[i].time then
Core.TimeoutCallbacks[i].cb()
Core.TimeoutCallbacks[i] = nil
end
end
end
+55 -35
View File
@@ -32,15 +32,14 @@ AddEventHandler('esx:playerLoaded', function(xPlayer, isNew, skin)
}, function()
TriggerServerEvent('esx:onPlayerSpawn')
TriggerEvent('esx:onPlayerSpawn')
TriggerEvent('playerSpawned') -- compatibility with old scripts
TriggerEvent('esx:restoreLoadout')
if isNew then
if skin.sex == 0 then
TriggerEvent('skinchanger:loadDefaultModel', true)
else
TriggerEvent('skinchanger:loadDefaultModel', false)
end
elseif skin then TriggerEvent('skinchanger:loadSkin', skin) end
TriggerEvent('skinchanger:loadDefaultModel', skin.sex == 0)
elseif skin then
TriggerEvent('skinchanger:loadSkin', skin)
end
TriggerEvent('esx:loadingScreenOff')
ShutdownLoadingScreen()
ShutdownLoadingScreenNui()
@@ -65,7 +64,7 @@ AddEventHandler('esx:playerLoaded', function(xPlayer, isNew, skin)
local gradeLabel = ESX.PlayerData.job.grade_label ~= ESX.PlayerData.job.label and ESX.PlayerData.job.grade_label or ''
if gradeLabel ~= '' then gradeLabel = ' - '..gradeLabel end
ESX.UI.HUD.RegisterElement('job', #ESX.PlayerData.accounts, 0, jobTpl, {
job_label = ESX.PlayerData.job.label,
grade_label = gradeLabel
@@ -83,10 +82,15 @@ end)
RegisterNetEvent('esx:setMaxWeight')
AddEventHandler('esx:setMaxWeight', function(newMaxWeight) ESX.PlayerData.maxWeight = newMaxWeight end)
AddEventHandler('esx:onPlayerSpawn', function()
ESX.SetPlayerData('ped', PlayerPedId())
ESX.SetPlayerData('dead', false)
end)
local function onPlayerSpawn()
if ESX.PlayerLoaded then
ESX.SetPlayerData('ped', PlayerPedId())
ESX.SetPlayerData('dead', false)
end
end
AddEventHandler('playerSpawned', onPlayerSpawn)
AddEventHandler('esx:onPlayerSpawn', onPlayerSpawn)
AddEventHandler('esx:onPlayerDeath', function()
ESX.SetPlayerData('ped', PlayerPedId())
@@ -235,18 +239,23 @@ end)
RegisterNetEvent('esx:spawnVehicle')
AddEventHandler('esx:spawnVehicle', function(vehicle)
local model = (type(vehicle) == 'number' and vehicle or GetHashKey(vehicle))
ESX.TriggerServerCallback("esx:isUserAdmin", function(admin)
if admin then
local model = (type(vehicle) == 'number' and vehicle or GetHashKey(vehicle))
if IsModelInCdimage(model) then
local playerCoords, playerHeading = GetEntityCoords(ESX.PlayerData.ped), GetEntityHeading(ESX.PlayerData.ped)
if IsModelInCdimage(model) then
local playerCoords, playerHeading = GetEntityCoords(ESX.PlayerData.ped), GetEntityHeading(ESX.PlayerData.ped)
ESX.Game.SpawnVehicle(model, playerCoords, playerHeading, function(vehicle)
TaskWarpPedIntoVehicle(ESX.PlayerData.ped, vehicle, -1)
end)
else
TriggerEvent('chat:addMessage', { args = { '^1SYSTEM', 'Invalid vehicle model.' } })
end
ESX.Game.SpawnVehicle(model, playerCoords, playerHeading, function(vehicle)
TaskWarpPedIntoVehicle(ESX.PlayerData.ped, vehicle, -1)
end)
else
TriggerEvent('chat:addMessage', { args = { '^1SYSTEM', 'Invalid vehicle model.' } })
end
end
end)
end)
RegisterNetEvent('esx:createPickup')
AddEventHandler('esx:createPickup', function(pickupId, label, coords, type, name, components, tintIndex)
local function setObjectProperties(object)
@@ -282,7 +291,7 @@ end)
RegisterNetEvent('esx:createMissingPickups')
AddEventHandler('esx:createMissingPickups', function(missingPickups)
for pickupId,pickup in pairs(missingPickups) do
for pickupId, pickup in pairs(missingPickups) do
TriggerEvent('esx:createPickup', pickupId, pickup.label, pickup.coords, pickup.type, pickup.name, pickup.components, pickup.tintIndex)
end
end)
@@ -346,13 +355,16 @@ end)
if Config.EnableHud then
Citizen.CreateThread(function()
local isPaused = false
local time = 500
while true do
Citizen.Wait(300)
Citizen.Wait(time)
if IsPauseMenuActive() and not isPaused then
time = 100
isPaused = true
ESX.UI.HUD.SetDisplay(0.0)
elseif not IsPauseMenuActive() and isPaused then
time = 100
isPaused = false
ESX.UI.HUD.SetDisplay(1.0)
end
@@ -488,32 +500,38 @@ end)
RegisterNetEvent("esx:tpm")
AddEventHandler("esx:tpm", function()
local WaypointHandle = GetFirstBlipInfoId(8)
if DoesBlipExist(WaypointHandle) then
local waypointCoords = GetBlipInfoIdCoord(WaypointHandle)
ESX.TriggerServerCallback("esx:isUserAdmin", function(admin)
if admin then
local WaypointHandle = GetFirstBlipInfoId(8)
if DoesBlipExist(WaypointHandle) then
local waypointCoords = GetBlipInfoIdCoord(WaypointHandle)
for height = 1, 1000 do
SetPedCoordsKeepVehicle(ESX.PlayerData.ped, waypointCoords["x"], waypointCoords["y"], height + 0.0)
for height = 1, 1000 do
SetPedCoordsKeepVehicle(ESX.PlayerData.ped, waypointCoords["x"], waypointCoords["y"], height + 0.0)
local foundGround, zPos = GetGroundZFor_3dCoord(waypointCoords["x"], waypointCoords["y"], height + 0.0)
local foundGround, zPos = GetGroundZFor_3dCoord(waypointCoords["x"], waypointCoords["y"], height + 0.0)
if foundGround then
SetPedCoordsKeepVehicle(ESX.PlayerData.ped, waypointCoords["x"], waypointCoords["y"], height + 0.0)
if foundGround then
SetPedCoordsKeepVehicle(ESX.PlayerData.ped, waypointCoords["x"], waypointCoords["y"], height + 0.0)
break
end
end
Citizen.Wait(5)
end
end
TriggerEvent('chatMessage', "Successfully Teleported")
else
else
TriggerEvent('chatMessage', "No Waypoint Set")
end
end
end
end)
end)
local noclip = false
RegisterNetEvent("esx:noclip")
AddEventHandler("esx:noclip", function(input)
ESX.TriggerServerCallback("esx:isUserAdmin", function(admin)
if admin then
local player = PlayerId()
local msg = "disabled"
@@ -528,7 +546,9 @@ AddEventHandler("esx:noclip", function(input)
end
TriggerEvent("chatMessage", "Noclip has been ^2^*" .. msg)
end
end)
end)
local heading = 0
Citizen.CreateThread(function()
+4 -23
View File
@@ -8,24 +8,14 @@ version 'legacy'
shared_scripts {
'locale.lua',
'locales/de.lua',
'locales/br.lua',
'locales/fr.lua',
'locales/en.lua',
'locales/fi.lua',
'locales/sv.lua',
'locales/pl.lua',
'locales/cs.lua',
'locales/sc.lua',
'locales/tc.lua',
'locales/*.lua',
'config.lua',
'config.weapons.lua',
}
server_scripts {
'@async/async.lua',
'@mysql-async/lib/MySQL.lua',
'@oxmysql/lib/MySQL.lua',
'server/common.lua',
'server/classes/player.lua',
@@ -78,16 +68,7 @@ files {
'html/img/accounts/money.png'
}
exports {
'getSharedObject'
}
server_exports {
'getSharedObject'
}
dependencies {
'mysql-async',
'async',
'oxmysql',
'spawnmanager',
}
}
+1 -1
View File
@@ -162,7 +162,7 @@ Locales['en'] = {
-- SMG & LMG
['weapon_assaultsmg'] = 'Assault SMG',
['weapon_combatmg'] = 'Combat MG',
['weapon_combatmg'] = 'Combat MG MK2',
['weapon_combatmg_mk2'] = 'Combat MG MK2',
['weapon_combatpdw'] = 'Combat PDW',
['weapon_gusenberg'] = 'Gusenberg Sweeper',
['weapon_machinepistol'] = 'Machine Pistol',
+346
View File
@@ -0,0 +1,346 @@
Locales['es'] = {
-- Inventory
['inventory'] = 'Inventario %s / %s',
['use'] = 'Usar',
['give'] = 'Dar',
['remove'] = 'Tirar',
['return'] = 'Volver',
['give_to'] = 'Dar a',
['amount'] = 'Cantidad',
['giveammo'] = 'Dar munición',
['amountammo'] = 'Cantidad de munición',
['noammo'] = 'No tienes suficiente munición!',
['gave_item'] = 'Has dado ~y~%sx~s~ ~b~%s~s~ a ~y~%s~s~',
['received_item'] = 'Has recibido ~y~%sx~s~ ~b~%s~s~ de ~b~%s~s~',
['gave_weapon'] = 'Has dado ~b~%s~s~ a ~y~%s~s~',
['gave_weapon_ammo'] = 'Has dado ~o~%sx %s~s~ para ~b~%s~s~ a ~y~%s~s~',
['gave_weapon_withammo'] = 'Has dado ~b~%s~s~ con ~o~%sx %s~s~ a ~y~%s~s~',
['gave_weapon_hasalready'] = '~y~%s~s~ ya tiene un/a ~y~%s~s~',
['gave_weapon_noweapon'] = '~y~%s~s~ no tiene ese arma',
['received_weapon'] = 'Has recibido ~b~%s~s~ de ~b~%s~s~',
['received_weapon_ammo'] = 'Has recibido ~o~%sx %s~s~ para su ~b~%s~s~ de ~b~%s~s~',
['received_weapon_withammo'] = 'Has recibido ~b~%s~s~ con ~o~%sx %s~s~ de ~b~%s~s~',
['received_weapon_hasalready'] = '~b~%s~s~ intentó darle un/a ~y~%s~s~, pero ya tienes uno',
['received_weapon_noweapon'] = '~b~%s~s~ intentó darles munición para un ~y~%s~s~, pero no tiene uno',
['gave_account_money'] = 'Has dado ~g~$%s~s~ (%s) a ~y~%s~s~',
['received_account_money'] = 'Has recibido ~g~$%s~s~ (%s) de ~b~%s~s~',
['amount_invalid'] = 'Cantidad inválida',
['players_nearby'] = 'No hay jugadores cerca',
['ex_inv_lim'] = 'Acción no posible, excediendo el límite de inventario para ~y~%s~s~',
['imp_invalid_quantity'] = 'Acción imposible, cantidad inválida',
['imp_invalid_amount'] = 'Acción imposible, cantidad inválida',
['threw_standard'] = 'Has tirado ~y~%sx~s~ ~b~%s~s~',
['threw_account'] = 'Has tirado ~g~$%s~s~ ~b~%s~s~',
['threw_weapon'] = 'Has tirado ~b~%s~s~',
['threw_weapon_ammo'] = 'Has tirado ~b~%s~s~ con ~o~%sx %s~s~',
['threw_weapon_already'] = 'Ya llevas el mismo arma',
['threw_cannot_pickup'] = 'No puedes recogerlo porque tu inventario está lleno!',
['threw_pickup_prompt'] = 'Pulsa ~y~E~s~ para recoger',
-- Key mapping
['keymap_showinventory'] = 'Ver Inventario',
-- Salary related
['received_salary'] = 'Has recibido tu sueldo: ~g~$%s~s~',
['received_help'] = 'Has recibido su cheque de bienestar: ~g~$%s~s~',
['company_nomoney'] = 'La empresa en la que trabajas no tiene dinero para pagar tu sueldo',
['received_paycheck'] = 'Recibió su paga',
['bank'] = 'Banco',
['account_bank'] = 'Banco',
['account_black_money'] = 'Dinero Negro',
['account_money'] = 'Efectivo',
['act_imp'] = 'Acción imposible',
['in_vehicle'] = 'No se puede dar nada a alguien en un vehículo',
-- Commands
['command_car'] = 'Generar un vehiculo',
['command_car_car'] = 'Nombre o hash del vehículo',
['command_cardel'] = 'Eliminar vehículos cercanos',
['command_cardel_radius'] = 'Opcional, eliminar todos los vehículos en el radio especificado',
['command_clear'] = 'Limpiar chat',
['command_clearall'] = 'Limpiar chat para todos los jugadores',
['command_clearinventory'] = 'Limpiar el inventario del jugador',
['command_clearloadout'] = 'Limpiar inventario de un jugador',
['command_giveaccountmoney'] = 'Dar dinero',
['command_giveaccountmoney_account'] = 'Nombre de cuenta válido',
['command_giveaccountmoney_amount'] = 'Cantidad a añadir',
['command_giveaccountmoney_invalid'] = 'Nombre de cuenta inválido',
['command_giveitem'] = 'Dar un objeto a un jugador',
['command_giveitem_item'] = 'Nombre del artículo',
['command_giveitem_count'] = 'Cantidad de articulos',
['command_giveweapon'] = 'Dar un arma a un jugador',
['command_giveweapon_weapon'] = 'Nombre del arma',
['command_giveweapon_ammo'] = 'Cantidad de municion',
['command_giveweapon_hasalready'] = 'El jugador ya tiene esa arma',
['command_giveweaponcomponent'] = 'Dar el componente del arma',
['command_giveweaponcomponent_component'] = 'Nombre del componente',
['command_giveweaponcomponent_invalid'] = 'Componente del arma no válido',
['command_giveweaponcomponent_hasalready'] = 'El jugador ya tiene ese componente del arma',
['command_giveweaponcomponent_missingweapon'] = 'El jugador no tiene esa arma',
['command_save'] = 'Guardar un jugador en la base de datos',
['command_saveall'] = 'Guardar todos los jugadores en la base de datos',
['command_setaccountmoney'] = 'Establecer el dinero de la cuenta para un jugador',
['command_setaccountmoney_amount'] = 'Cantidad de dinero para fijar',
['command_setcoords'] = 'Teletransporte a coordenadas',
['command_setcoords_x'] = 'Eje X',
['command_setcoords_y'] = 'Eje Y',
['command_setcoords_z'] = 'Eje Z',
['command_setjob'] = 'Dar un trabajo a un jugador',
['command_setjob_job'] = 'Nombre del trabajo',
['command_setjob_grade'] = 'Rango del trabajo',
['command_setjob_invalid'] = 'El trabajo, el rango o ambos no son válidos',
['command_setgroup'] = 'Establecer el grupo de un jugador',
['command_setgroup_group'] = 'Nombre del grupo',
['commanderror_argumentmismatch'] = 'error en el recuento de argumentos (pasado %s, deseado %s)',
['commanderror_argumentmismatch_number'] = 'argumento #%s tipo no coincide (cadena pasada, número deseado)',
['commanderror_invaliditem'] = 'Nombre del artículo no válido',
['commanderror_invalidweapon'] = 'Arma inválida',
['commanderror_console'] = 'Ese comando no se puede ejecutar desde la consola',
['commanderror_invalidcommand'] = '^3%s^0 ¡No es un comando válido!',
['commanderror_invalidplayerid'] = 'No hay ningún jugador en línea que coincida con la ID del servidor',
['commandgeneric_playerid'] = 'ID del jugador',
-- Locale settings
['locale_digit_grouping_symbol'] = ',',
['locale_currency'] = '$%s',
-- Weapons
-- Melee
['weapon_dagger'] = 'Daga',
['weapon_bat'] = 'Bate',
['weapon_battleaxe'] = 'Hacha de combate',
['weapon_bottle'] = 'Botella',
['weapon_crowbar'] = 'Palanca',
['weapon_flashlight'] = 'Linterna',
['weapon_golfclub'] = 'Palos de Golf',
['weapon_hammer'] = 'Martillo',
['weapon_hatchet'] = 'Hacha',
['weapon_knife'] = 'Cuchillo',
['weapon_knuckle'] = 'Puños Americanos',
['weapon_machete'] = 'Machete',
['weapon_nightstick'] = 'Porra',
['weapon_wrench'] = 'Llave Inglesa',
['weapon_poolcue'] = 'Taco de Billar',
['weapon_stone_hatchet'] = 'Hacha de Piedra',
['weapon_switchblade'] = 'Navaja',
-- Handguns
['weapon_appistol'] = 'Pistola AP ',
['weapon_ceramicpistol'] = 'Pistola Corta',
['weapon_combatpistol'] = 'Pistola Combate',
['weapon_doubleaction'] = 'Revólver de Doble Acción',
['weapon_navyrevolver'] = 'Revólver de la Armada',
['weapon_flaregun'] = 'Pistola de Bengalas',
['weapon_gadgetpistol'] = 'Pistola de Perico',
['weapon_heavypistol'] = 'Pistola Pesada',
['weapon_revolver'] = 'Revólver Pesado',
['weapon_revolver_mk2'] = 'Revólver Pesado MK2',
['weapon_marksmanpistol'] = 'Pistola Marksman',
['weapon_pistol'] = 'Pistola',
['weapon_pistol_mk2'] = 'Pistola MK2',
['weapon_pistol50'] = 'Pistola .50',
['weapon_snspistol'] = 'Pistola SNS',
['weapon_snspistol_mk2'] = 'Pistola SNS MK2',
['weapon_stungun'] = 'Tazer',
['weapon_raypistol'] = 'Up-N-Atomizer',
['weapon_vintagepistol'] = 'Pistola Vintage',
-- Shotguns
['weapon_assaultshotgun'] = 'Escopeta de Asalto',
['weapon_autoshotgun'] = 'Escopeta Automática',
['weapon_bullpupshotgun'] = 'Escopeta Bullpup',
['weapon_combatshotgun'] = 'Escopeta Combate',
['weapon_dbshotgun'] = 'Escopeta de Doble Barril',
['weapon_heavyshotgun'] = 'Escopeta Pesada',
['weapon_musket'] = 'Mosquete',
['weapon_pumpshotgun'] = 'Escopeta de Bombeo',
['weapon_pumpshotgun_mk2'] = 'Escopeta de Bombeo MK2',
['weapon_sawnoffshotgun'] = 'Escopeta Recortada',
-- SMG & LMG
['weapon_assaultsmg'] = 'Subfusil de Asalto',
['weapon_combatmg'] = 'Ametralladora de Combate',
['weapon_combatmg'] = 'Ametralladora MK2',
['weapon_combatpdw'] = 'Subfusil PDW',
['weapon_gusenberg'] = 'Subfusil de Barril',
['weapon_machinepistol'] = 'Pistola Ametralladora',
['weapon_mg'] = 'Ametralladora',
['weapon_microsmg'] = 'Micro Subfusil',
['weapon_minismg'] = 'Mini Subfusil',
['weapon_smg'] = 'Subfusil',
['weapon_smg_mk2'] = 'Subfusil MK2',
['weapon_raycarbine'] = 'Ametralladora de Rayos',
-- Rifles
['weapon_advancedrifle'] = 'Rifle Avanzado',
['weapon_assaultrifle'] = 'Rifle de Asalto',
['weapon_assaultrifle_mk2'] = 'Rifle de Asalto MK2',
['weapon_bullpuprifle'] = 'Rifle Bullpup',
['weapon_bullpuprifle_mk2'] = 'Rifle Bullpup MK2',
['weapon_carbinerifle'] = 'Carabina',
['weapon_carbinerifle_mk2'] = 'Carabina MK2',
['weapon_compactrifle'] = 'Rifle Compacto',
['weapon_militaryrifle'] = 'Rifle Militar',
['weapon_specialcarbine'] = 'Carabina Especial',
['weapon_specialcarbine_mk2'] = 'Carabina Especial MK2',
-- Sniper
['weapon_heavysniper'] = 'Francotirador Pesado',
['weapon_heavysniper_mk2'] = 'Francotirador Pesado MK2',
['weapon_marksmanrifle'] = 'Rifle Marksman',
['weapon_marksmanrifle_mk2'] = 'Rifle Marksman MK2',
['weapon_sniperrifle'] = 'Rifle de Francotirador',
-- Heavy / Launchers
['weapon_compactlauncher'] = 'Lanzador Compacto',
['weapon_firework'] = 'Lanzador de Fuegos Artificiales',
['weapon_grenadelauncher'] = 'Lanzagranadas',
['weapon_hominglauncher'] = 'Lanzacohetes Guiado',
['weapon_minigun'] = 'Minigun',
['weapon_railgun'] = 'Cañón de riel',
['weapon_rpg'] = 'Lanzador de cohetes',
['weapon_rayminigun'] = 'Minigun de Rayos',
-- Thrown
['weapon_ball'] = 'Pelota de Beisbol',
['weapon_bzgas'] = 'Gas Pimienta',
['weapon_flare'] = 'Bengala',
['weapon_grenade'] = 'Granada',
['weapon_petrolcan'] = 'Bidon de Gasolina',
['weapon_hazardcan'] = 'Bidón de Gasolina Peligroso',
['weapon_molotov'] = 'Molotov',
['weapon_proxmine'] = 'Mina de Proximidad ',
['weapon_pipebomb'] = 'Bomba de Tubo',
['weapon_snowball'] = 'Bola de nieve',
['weapon_stickybomb'] = 'Bomba Pegajosa',
['weapon_smokegrenade'] = 'Granada de Humo',
-- Special
['weapon_fireextinguisher'] = 'Extintor',
['weapon_digiscanner'] = 'Escaner Digital',
['weapon_garbagebag'] = 'Bolsa de Basura',
['weapon_handcuffs'] = 'Grilletes',
['gadget_nightvision'] = 'Vision Nocturna',
['gadget_parachute'] = 'Paracaidas',
-- Weapon Components
['component_knuckle_base'] = 'Modelo Basico',
['component_knuckle_pimp'] = 'el Proxeneta',
['component_knuckle_ballas'] = 'los Ballas',
['component_knuckle_dollar'] = 'el Buscavidas',
['component_knuckle_diamond'] = 'la Roca',
['component_knuckle_hate'] = 'el Hater',
['component_knuckle_love'] = 'el Amante',
['component_knuckle_player'] = 'el Jugador',
['component_knuckle_king'] = 'el Rey',
['component_knuckle_vagos'] = 'los Vagos',
['component_luxary_finish'] = 'Acabado de Armas de Lujo',
['component_handle_default'] = 'Mango Default',
['component_handle_vip'] = 'Mango VIP',
['component_handle_bodyguard'] = 'Mango de Guardaespaldas',
['component_vip_finish'] = 'Acabado VIP',
['component_bodyguard_finish'] = 'Acabado Guardaespaldas',
['component_camo_finish'] = 'Camuflaje Digital',
['component_camo_finish2'] = 'Camuflaje Pincelada',
['component_camo_finish3'] = 'Camuflaje Bosque',
['component_camo_finish4'] = 'Camuflaje Calavera',
['component_camo_finish5'] = 'Camuflaje Sessanta Nove',
['component_camo_finish6'] = 'Camuflaje Perseo',
['component_camo_finish7'] = 'Camuflaje Leopardo',
['component_camo_finish8'] = 'Camuflaje Zebra',
['component_camo_finish9'] = 'Camuflaje Geométrico',
['component_camo_finish10'] = 'Camuflaje Boom',
['component_camo_finish11'] = 'Camuflaje Patriotico',
['component_camo_slide_finish'] = 'Camuflaje Digital Deslizante',
['component_camo_slide_finish2'] = 'Camuflaje Pincelada Deslizante',
['component_camo_slide_finish3'] = 'Camuflaje Bosque Deslizante',
['component_camo_slide_finish4'] = 'Camuflaje Calavera Deslizante',
['component_camo_slide_finish5'] = 'Camuflaje Sessanta Nove Deslizante',
['component_camo_slide_finish6'] = 'Camuflaje Perseo Deslizante',
['component_camo_slide_finish7'] = 'Camuflaje Leopardo Deslizante',
['component_camo_slide_finish8'] = 'Camuflaje Zebra Deslizante',
['component_camo_slide_finish9'] = 'Camuflaje Geométrico Deslizante',
['component_camo_slide_finish10'] = 'Camuflaje Boom Deslizante',
['component_camo_slide_finish11'] = 'Camuflaje Patriotico Deslizante',
['component_clip_default'] = 'Cargador Default',
['component_clip_extended'] = 'Cargador Extendido',
['component_clip_drum'] = 'Cargador Barril',
['component_clip_box'] = 'Caja de Cargador',
['component_scope_holo'] = 'Mira Holográfico',
['component_scope_small'] = 'Mira Pequeña',
['component_scope_medium'] = 'Mira Mediana',
['component_scope_large'] = 'Mira Larga',
['component_scope'] = 'Mira',
['component_scope_advanced'] = 'Mira Avanzada',
['component_ironsights'] = 'Mira de Hierro',
['component_suppressor'] = 'Supresor',
['component_compensator'] = 'Compensador',
['component_muzzle_flat'] = 'Boquilla de Freno Plana',
['component_muzzle_tactical'] = 'Boquilla de Freno Tactica',
['component_muzzle_fat'] = 'Boquilla de Freno Punta Gorda',
['component_muzzle_precision'] = 'Boquilla de Freno de Precision',
['component_muzzle_heavy'] = 'Boquilla de Freno Pesada',
['component_muzzle_slanted'] = 'Boquilla de Freno inclinada',
['component_muzzle_split'] = 'Boquilla de Freno de Puntas Abiertas',
['component_muzzle_squared'] = 'Boquilla de Freno Cuadrada',
['component_flashlight'] = 'Linterna',
['component_grip'] = 'Agarre',
['component_barrel_default'] = 'Barril Por Defecto',
['component_barrel_heavy'] = 'Barril Pesado',
['component_ammo_tracer'] = 'Munición de Rastreo',
['component_ammo_incendiary'] = 'Munición Incendiaria',
['component_ammo_hollowpoint'] = 'Munición de Punta Hueca',
['component_ammo_fmj'] = 'Munición fMJ',
['component_ammo_armor'] = 'Munición Perforante para Blindaje',
['component_ammo_explosive'] = 'Munición Incendiaria Perforadora de Blindajes',
['component_shells_default'] = 'Casquillos Por Defecto',
['component_shells_incendiary'] = 'Casquillos Aliento de Dragón',
['component_shells_armor'] = 'Casquillos Perdigones de Acero',
['component_shells_hollowpoint'] = 'Casquillos Punta Hueca',
['component_shells_explosive'] = 'Casquillos Posta Explosiva',
-- Weapon Ammo
['ammo_rounds'] = 'Redonda/s',
['ammo_shells'] = 'Casquillo/s',
['ammo_charge'] = 'Carga',
['ammo_petrol'] = 'Galones de Combustible',
['ammo_firework'] = 'Fuegos Artificiale/s',
['ammo_rockets'] = 'Cohete/s',
['ammo_grenadelauncher'] = 'Granada/s',
['ammo_grenade'] = 'Granada/s',
['ammo_stickybomb'] = 'Bomba/s',
['ammo_pipebomb'] = 'Bomba/s',
['ammo_smokebomb'] = 'Bomba/s',
['ammo_molotov'] = 'Molotov/s',
['ammo_proxmine'] = 'Mina(s)',
['ammo_bzgas'] = 'Lata(s)',
['ammo_ball'] = 'Bola(s)',
['ammo_snowball'] = 'Bola(s)',
['ammo_flare'] = 'Bengala(s)',
['ammo_flaregun'] = 'Bengala(s)',
-- Weapon Tints
['tint_default'] = 'Skin Por Defecto',
['tint_green'] = 'Skin Verde',
['tint_gold'] = 'Skin Oro',
['tint_pink'] = 'Skin Rosa',
['tint_army'] = 'Skin Militar',
['tint_lspd'] = 'Skin Azul',
['tint_orange'] = 'Skin Naranja',
['tint_platinum'] = 'Skin Plata',
}
+1 -1
View File
@@ -14,7 +14,7 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory,
self.variables = {}
self.weight = weight
self.maxWeight = Config.MaxWeight
if Config.Multichar then self.license = 'license'..string.sub(identifier, 6) else self.license = 'license:'..identifier end
if Config.Multichar then self.license = 'license'.. identifier:sub(identifier:find(':'), identifier:len()) else self.license = 'license:'..identifier end
ExecuteCommand(('add_principal identifier.%s group.%s'):format(self.license, self.group))
+9 -14
View File
@@ -19,7 +19,7 @@ end, true, {help = _U('command_setjob'), validate = true, arguments = {
}})
ESX.RegisterCommand('car', 'admin', function(xPlayer, args, showError)
if not args.car then args.car = "baller2" end
if not args.car then args.car = "Prototipo" end
xPlayer.triggerEvent('esx:spawnVehicle', args.car)
end, false, {help = _U('command_car'), validate = false, arguments = {
{name = 'car', help = _U('command_car_car'), type = 'any'}
@@ -134,31 +134,32 @@ end, true, {help = _U('command_setgroup'), validate = true, arguments = {
}})
ESX.RegisterCommand('save', 'admin', function(xPlayer, args, showError)
ESX.SavePlayer(args.playerId)
Core.SavePlayer(args.playerId)
print("[^2Info^0] Saved Player!")
end, true, {help = _U('command_save'), validate = true, arguments = {
{name = 'playerId', help = _U('commandgeneric_playerid'), type = 'player'}
}})
ESX.RegisterCommand('saveall', 'admin', function(xPlayer, args, showError)
ESX.SavePlayers()
Core.SavePlayers()
end, true, {help = _U('command_saveall')})
ESX.RegisterCommand('group', {"user", "admin"}, function(xPlayer, args, showError)
print(xPlayer.getName()..", You are currently: ^5".. xPlayer.getGroup())
print(xPlayer.getName()..", You are currently: ^5".. xPlayer.getGroup() .. "^0")
end, true)
ESX.RegisterCommand('job', {"user", "admin"}, function(xPlayer, args, showError)
print(xPlayer.getName()..", You are currently: ^5".. xPlayer.getJob().name.. "^0 - ^5".. xPlayer.getJob().grade_label)
print(xPlayer.getName()..", You are currently: ^5".. xPlayer.getJob().name.. "^0 - ^5".. xPlayer.getJob().grade_label .. "^0")
end, true)
ESX.RegisterCommand('info', {"user", "admin"}, function(xPlayer, args, showError)
local job = xPlayer.getJob().name
local jobgrade = xPlayer.getJob().grade_name
print("^2ID : ^5"..xPlayer.source.." ^0| ^2Name:^5"..xPlayer.getName().." ^0 | ^2Group:^5"..xPlayer.getGroup().."^0 | ^2Job:^5".. job.."")
print("^2ID : ^5"..xPlayer.source.." ^0| ^2Name:^5"..xPlayer.getName().." ^0 | ^2Group:^5"..xPlayer.getGroup().."^0 | ^2Job:^5".. job.."^0")
end, true)
ESX.RegisterCommand('coords', "admin", function(xPlayer, args, showError)
print("".. xPlayer.getName().. ": ^5".. xPlayer.getCoords(true))
print("Coords:^5 ".. GetEntityCoords(GetPlayerPed(xPlayer.source)).. "^0")
end, true)
ESX.RegisterCommand('tpm', "admin", function(xPlayer, args, showError)
@@ -180,7 +181,7 @@ end, true, {help = _U('bring'), validate = true, arguments = {
}})
ESX.RegisterCommand('kill', "admin", function(xPlayer, args, showError)
args.playerId.triggerEvent('esx:killPlayer')
args.playerId.triggerEvent("esx:killPlayer")
end, true, {help = _U('kill'), validate = true, arguments = {
{name = 'playerId', help = _U('commandgeneric_playerid'), type = 'player'}
}})
@@ -197,12 +198,6 @@ end, true, {help = _U('kill'), validate = true, arguments = {
{name = 'playerId', help = _U('commandgeneric_playerid'), type = 'player'}
}})
ESX.RegisterCommand('reviveall', "admin", function(xPlayer, args, showError)
for _, playerId in ipairs(GetPlayers()) do
TriggerClientEvent('esx_ambulancejob:revive', playerId)
end
end, false)
ESX.RegisterCommand("noclip", 'admin', function(xPlayer, args, showError)
xPlayer.triggerEvent('esx:noclip')
end, false)
+15 -14
View File
@@ -1,34 +1,35 @@
ESX = {}
ESX.Players = {}
ESX.UsableItemsCallbacks = {}
ESX.Items = {}
ESX.ServerCallbacks = {}
ESX.TimeoutCount = -1
ESX.CancelledTimeouts = {}
ESX.Pickups = {}
ESX.PickupId = 0
ESX.Jobs = {}
ESX.RegisteredCommands = {}
ESX.Items = {}
Core = {}
Core.UsableItemsCallbacks = {}
Core.ServerCallbacks = {}
Core.TimeoutCount = -1
Core.CancelledTimeouts = {}
Core.RegisteredCommands = {}
Core.Pickups = {}
Core.PickupId = 0
AddEventHandler('esx:getSharedObject', function(cb)
cb(ESX)
end)
function getSharedObject()
exports('getSharedObject', function()
return ESX
end
end)
local function StartDBSync()
Citizen.CreateThread(function()
while true do
Citizen.Wait(10 * 60 * 1000)
ESX.SavePlayers()
Core.SavePlayers()
end
end)
end
MySQL.ready(function()
MySQL.Async.fetchAll('SELECT * FROM items', {}, function(result)
MySQL.query('SELECT * FROM items', {}, function(result)
for k,v in ipairs(result) do
ESX.Items[v.name] = {
label = v.label,
@@ -40,13 +41,13 @@ MySQL.ready(function()
end)
local Jobs = {}
MySQL.Async.fetchAll('SELECT * FROM jobs', {}, function(jobs)
MySQL.query('SELECT * FROM jobs', {}, function(jobs)
for k,v in ipairs(jobs) do
Jobs[v.name] = v
Jobs[v.name].grades = {}
end
MySQL.Async.fetchAll('SELECT * FROM job_grades', {}, function(jobGrades)
MySQL.query('SELECT * FROM job_grades', {}, function(jobGrades)
for k,v in ipairs(jobGrades) do
if Jobs[v.job_name] then
Jobs[v.job_name].grades[tostring(v.grade)] = v
+76 -79
View File
@@ -5,17 +5,17 @@ ESX.Trace = function(msg)
end
ESX.SetTimeout = function(msec, cb)
local id = ESX.TimeoutCount + 1
local id = Core.TimeoutCount + 1
SetTimeout(msec, function()
if ESX.CancelledTimeouts[id] then
ESX.CancelledTimeouts[id] = nil
if Core.CancelledTimeouts[id] then
Core.CancelledTimeouts[id] = nil
else
cb()
end
end)
ESX.TimeoutCount = id
Core.TimeoutCount = id
return id
end
@@ -29,10 +29,10 @@ ESX.RegisterCommand = function(name, group, cb, allowConsole, suggestion)
return
end
if ESX.RegisteredCommands[name] then
if Core.RegisteredCommands[name] then
print(('[^3WARNING^7] Command ^5"%s" already registered, overriding command'):format(name))
if ESX.RegisteredCommands[name].suggestion then
if Core.RegisteredCommands[name].suggestion then
TriggerClientEvent('chat:removeSuggestion', -1, ('/%s'):format(name))
end
end
@@ -44,10 +44,10 @@ ESX.RegisterCommand = function(name, group, cb, allowConsole, suggestion)
TriggerClientEvent('chat:addSuggestion', -1, ('/%s'):format(name), suggestion.help, suggestion.arguments)
end
ESX.RegisteredCommands[name] = {group = group, cb = cb, allowConsole = allowConsole, suggestion = suggestion}
Core.RegisteredCommands[name] = {group = group, cb = cb, allowConsole = allowConsole, suggestion = suggestion}
RegisterCommand(name, function(playerId, args, rawCommand)
local command = ESX.RegisteredCommands[name]
local command = Core.RegisteredCommands[name]
if not command.allowConsole and playerId == 0 then
print(('[^3WARNING^7] ^5%s'):format(_U('commanderror_console')))
@@ -148,92 +148,62 @@ ESX.RegisterCommand = function(name, group, cb, allowConsole, suggestion)
end
ESX.ClearTimeout = function(id)
ESX.CancelledTimeouts[id] = true
Core.CancelledTimeouts[id] = true
end
ESX.RegisterServerCallback = function(name, cb)
ESX.ServerCallbacks[name] = cb
Core.ServerCallbacks[name] = cb
end
ESX.TriggerServerCallback = function(name, requestId, source, cb, ...)
if ESX.ServerCallbacks[name] then
ESX.ServerCallbacks[name](source, cb, ...)
if Core.ServerCallbacks[name] then
Core.ServerCallbacks[name](source, cb, ...)
else
print(('[^3WARNING^7] Server callback ^5"%s"^0 does not exist. ^1Please Check The Server File for Errors!'):format(name))
end
end
local savePlayers = -1
Citizen.CreateThread(function()
savePlayers = MySQL.Sync.store("UPDATE users SET `accounts` = ?, `job` = ?, `job_grade` = ?, `group` = ?, `position` = ?, `inventory` = ?, `loadout` = ? WHERE `identifier` = ?")
end)
ESX.SavePlayer = function(xPlayer, cb)
local asyncTasks = {}
table.insert(asyncTasks, function(cb2)
MySQL.Async.execute(savePlayers, {
json.encode(xPlayer.getAccounts(true)),
xPlayer.job.name,
xPlayer.job.grade,
xPlayer.getGroup(),
json.encode(xPlayer.getCoords()),
json.encode(xPlayer.getInventory(true)),
json.encode(xPlayer.getLoadout(true)),
xPlayer.getIdentifier()
}, function(rowsChanged)
cb2()
end)
end)
Async.parallel(asyncTasks, function(results)
print(('[^2INFO^7] Saved player ^5"%s^7"'):format(xPlayer.getName()))
if cb then
cb()
Core.SavePlayer = function(xPlayer, cb)
MySQL.prepare('UPDATE `users` SET `accounts` = ?, `job` = ?, `job_grade` = ?, `group` = ?, `position` = ?, `inventory` = ?, `loadout` = ? WHERE `identifier` = ?', {
json.encode(xPlayer.getAccounts(true)),
xPlayer.job.name,
xPlayer.job.grade,
xPlayer.group,
json.encode(xPlayer.getCoords()),
json.encode(xPlayer.getInventory(true)),
json.encode(xPlayer.getLoadout(true)),
xPlayer.identifier
}, function(affectedRows)
if affectedRows == 1 then
print(('[^2INFO^7] Saved player ^5"%s^7"'):format(xPlayer.name))
end
if cb then cb() end
end)
end
ESX.SavePlayers = function(cb)
Core.SavePlayers = function(cb)
local xPlayers = ESX.GetExtendedPlayers()
if #xPlayers > 0 then
local count = #xPlayers
if count > 0 then
local parameters = {}
local time = os.time()
local selectListWithNames = "SELECT '%s' AS identifier, '%s' AS new_accounts, '%s' AS new_job, %s AS new_job_grade, '%s' AS new_group, '%s' AS new_loadout, '%s' AS new_position, '%s' AS new_inventory "
local selectListNoNames = "SELECT '%s', '%s', '%s' , %s, '%s', '%s', '%s', '%s' "
local updateCommand = 'UPDATE users u JOIN ('
local selectList = selectListNoNames
local first = true
for k, xPlayer in pairs(xPlayers) do
if first == false then
updateCommand = updateCommand .. ' UNION '
else
selectList = selectListWithNames
end
updateCommand = updateCommand .. string.format(selectList,
xPlayer.identifier,
for i=1, count do
local xPlayer = xPlayers[i]
parameters[#parameters+1] = {
json.encode(xPlayer.getAccounts(true)),
xPlayer.job.name,
xPlayer.job.grade,
xPlayer.getGroup(),
json.encode(xPlayer.getLoadout(true)),
xPlayer.group,
json.encode(xPlayer.getCoords()),
json.encode(xPlayer.getInventory(true))
)
first = false
json.encode(xPlayer.getInventory(true)),
json.encode(xPlayer.getLoadout(true)),
xPlayer.identifier
}
end
updateCommand = updateCommand .. ' ) vals ON u.identifier = vals.identifier SET accounts = new_accounts, job = new_job, job_grade = new_job_grade, `group` = new_group, loadout = new_loadout, `position` = new_position, inventory = new_inventory'
MySQL.Async.fetchAll(updateCommand, {},
function(result)
if result then
if cb then cb() else print(('[^2INFO^7] Saved %s of %s player(s) over %s seconds'):format(result.affectedRows, #xPlayers, os.time() - time)) end
MySQL.prepare("UPDATE `users` SET `accounts` = ?, `job` = ?, `job_grade` = ?, `group` = ?, `position` = ?, `inventory` = ?, `loadout` = ? WHERE `identifier` = ?", parameters,
function(results)
if results then
if type(cb) == 'function' then cb() else print(('[^2INFO^7] Saved %s %s over %s ms'):format(count, count > 1 and 'players' or 'player', (os.time() - time) / 1000000)) end
end
end)
end
@@ -285,11 +255,11 @@ ESX.GetIdentifier = function(playerId)
end
ESX.RegisterUsableItem = function(item, cb)
ESX.UsableItemsCallbacks[item] = cb
Core.UsableItemsCallbacks[item] = cb
end
ESX.UseItem = function(source, item)
ESX.UsableItemsCallbacks[item](source, item)
Core.UsableItemsCallbacks[item](source, item)
end
ESX.GetItemLabel = function(item)
@@ -298,24 +268,36 @@ ESX.GetItemLabel = function(item)
end
end
ESX.GetJobs = function()
return ESX.Jobs
end
ESX.GetUsableItems = function()
local Usables = {}
for k in pairs(Core.UsableItemsCallbacks) do
Usables[k] = true
end
return Usables
end
ESX.CreatePickup = function(type, name, count, label, playerId, components, tintIndex)
local pickupId = (ESX.PickupId == 65635 and 0 or ESX.PickupId + 1)
local pickupId = (Core.PickupId == 65635 and 0 or Core.PickupId + 1)
local xPlayer = ESX.GetPlayerFromId(playerId)
local coords = xPlayer.getCoords()
ESX.Pickups[pickupId] = {
Core.Pickups[pickupId] = {
type = type, name = name,
count = count, label = label,
coords = coords
}
if type == 'item_weapon' then
ESX.Pickups[pickupId].components = components
ESX.Pickups[pickupId].tintIndex = tintIndex
Core.Pickups[pickupId].components = components
Core.Pickups[pickupId].tintIndex = tintIndex
end
TriggerClientEvent('esx:createPickup', -1, pickupId, label, coords, type, name, components, tintIndex)
ESX.PickupId = pickupId
Core.PickupId = pickupId
end
ESX.DoesJobExist = function(job, grade)
@@ -329,3 +311,18 @@ ESX.DoesJobExist = function(job, grade)
return false
end
Core.IsPlayerAdmin = function(playerId)
if (IsPlayerAceAllowed(playerId, 'command') or GetConvar('sv_lan', '') == 'true') and true or false then
return true
end
local xPlayer = ESX.GetPlayerFromId(playerId)
if xPlayer then
if xPlayer.group == 'admin' then
return true
end
end
return false
end
+211 -230
View File
@@ -1,27 +1,18 @@
local NewPlayer, LoadPlayer = -1, -1
Citizen.CreateThread(function()
SetMapName('San Andreas')
SetGameType('ESX Legacy')
SetMapName('San Andreas')
SetGameType('ESX Legacy')
local query = '`accounts`, `job`, `job_grade`, `group`, `position`, `inventory`, `skin`, `loadout`' -- Select these fields from the database
if Config.Multichar or Config.Identity then -- append these fields to the select query
query = query..', `firstname`, `lastname`, `dateofbirth`, `sex`, `height`'
end
local newPlayer = 'INSERT INTO `users` SET `accounts` = ?, `identifier` = ?, `group` = ?'
local loadPlayer = 'SELECT `accounts`, `job`, `job_grade`, `group`, `position`, `inventory`, `skin`, `loadout`'
if Config.Multichar then -- insert identity data with creation
MySQL.Async.store("INSERT INTO `users` SET `accounts` = ?, `identifier` = ?, `group` = ?, `firstname` = ?, `lastname` = ?, `dateofbirth` = ?, `sex` = ?, `height` = ?", function(storeId)
NewPlayer = storeId
end)
else
MySQL.Async.store("INSERT INTO `users` SET `accounts` = ?, `identifier` = ?, `group` = ?", function(storeId)
NewPlayer = storeId
end)
end
if Config.Multichar then
newPlayer = newPlayer..', `firstname` = ?, `lastname` = ?, `dateofbirth` = ?, `sex` = ?, `height` = ?'
end
MySQL.Async.store("SELECT "..query.." FROM `users` WHERE identifier = ?", function(storeId)
LoadPlayer = storeId
end)
end)
if Config.Multichar or Config.Identity then
loadPlayer = loadPlayer..', `firstname`, `lastname`, `dateofbirth`, `sex`, `height`'
end
loadPlayer = loadPlayer..' FROM `users` WHERE identifier = ?'
if Config.Multichar then
AddEventHandler('esx:onPlayerJoined', function(src, char, data)
@@ -49,13 +40,12 @@ function onPlayerJoined(playerId)
if ESX.GetPlayerFromIdentifier(identifier) then
DropPlayer(playerId, ('there was an error loading your character!\nError code: identifier-active-ingame\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same Rockstar account.\n\nYour Rockstar identifier: %s'):format(identifier))
else
MySQL.Async.fetchScalar('SELECT 1 FROM users WHERE identifier = @identifier', {
['@identifier'] = identifier
}, function(result)
if result then
loadESXPlayer(identifier, playerId, false)
else createESXPlayer(identifier, playerId) end
end)
local result = MySQL.scalar.await('SELECT 1 FROM users WHERE identifier = ?', { identifier })
if result then
loadESXPlayer(identifier, playerId, false)
else
createESXPlayer(identifier, playerId)
end
end
else
DropPlayer(playerId, 'there was an error loading your character!\nError code: identifier-missing-ingame\n\nThe cause of this error is not known, your identifier could not be found. Please come back later or report this problem to the server administration team.')
@@ -69,7 +59,7 @@ function createESXPlayer(identifier, playerId, data)
accounts[account] = money
end
if IsPlayerAceAllowed(playerId, "command") then
if Core.IsPlayerAdmin(playerId) then
print(('^2[INFO] ^0 Player ^5%s ^0Has been granted admin permissions via ^5Ace Perms.^7'):format(playerId))
defaultGroup = "admin"
else
@@ -77,49 +67,44 @@ function createESXPlayer(identifier, playerId, data)
end
if not Config.Multichar then
MySQL.Async.execute(NewPlayer, {
json.encode(accounts),
identifier,
defaultGroup,
}, function(rowsChanged)
MySQL.prepare(newPlayer, { json.encode(accounts), identifier, defaultGroup }, function()
loadESXPlayer(identifier, playerId, true)
end)
else
MySQL.Async.execute(NewPlayer, {
json.encode(accounts),
identifier,
defaultGroup,
data.firstname,
data.lastname,
data.dateofbirth,
data.sex,
data.height,
}, function(rowsChanged)
MySQL.prepare(newPlayer, {
json.encode(accounts),
identifier,
defaultGroup,
data.firstname,
data.lastname,
data.dateofbirth,
data.sex,
data.height
}, function()
loadESXPlayer(identifier, playerId, true)
end)
end
end
AddEventHandler('playerConnecting', function(name, setCallback, deferrals)
deferrals.defer()
local playerId = source
local identifier = ESX.GetIdentifier(playerId)
Citizen.Wait(100)
if not Config.Multichar then
AddEventHandler('playerConnecting', function(name, setCallback, deferrals)
deferrals.defer()
local playerId = source
local identifier = ESX.GetIdentifier(playerId)
if identifier then
if ESX.GetPlayerFromIdentifier(identifier) then
deferrals.done(('There was an error loading your character!\nError code: identifier-active\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same account.\n\nYour identifier: %s'):format(identifier))
if identifier then
if ESX.GetPlayerFromIdentifier(identifier) then
deferrals.done(('There was an error loading your character!\nError code: identifier-active\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same account.\n\nYour identifier: %s'):format(identifier))
else
deferrals.done()
end
else
deferrals.done()
deferrals.done('There was an error loading your character!\nError code: identifier-missing\n\nThe cause of this error is not known, your identifier could not be found. Please come back later or report this problem to the server administration team.')
end
else
deferrals.done('There was an error loading your character!\nError code: identifier-missing\n\nThe cause of this error is not known, your identifier could not be found. Please come back later or report this problem to the server administration team.')
end
end)
end)
end
function loadESXPlayer(identifier, playerId, isNew)
local tasks = {}
local userData = {
accounts = {},
inventory = {},
@@ -129,179 +114,171 @@ function loadESXPlayer(identifier, playerId, isNew)
weight = 0
}
table.insert(tasks, function(cb)
MySQL.Async.fetchAll(LoadPlayer, { identifier
}, function(result)
local job, grade, jobObject, gradeObject = result[1].job, tostring(result[1].job_grade)
local foundAccounts, foundItems = {}, {}
local result = MySQL.prepare.await(loadPlayer, { identifier })
local job, grade, jobObject, gradeObject = result.job, tostring(result.job_grade)
local foundAccounts, foundItems = {}, {}
-- Accounts
if result[1].accounts and result[1].accounts ~= '' then
local accounts = json.decode(result[1].accounts)
-- Accounts
if result.accounts and result.accounts ~= '' then
local accounts = json.decode(result.accounts)
for account,money in pairs(accounts) do
foundAccounts[account] = money
end
end
for account,label in pairs(Config.Accounts) do
table.insert(userData.accounts, {
name = account,
money = foundAccounts[account] or Config.StartingAccountMoney[account] or 0,
label = label
})
end
-- Job
if ESX.DoesJobExist(job, grade) then
jobObject, gradeObject = ESX.Jobs[job], ESX.Jobs[job].grades[grade]
else
print(('[^3WARNING^7] Ignoring invalid job for %s [job: %s, grade: %s]'):format(identifier, job, grade))
job, grade = 'unemployed', '0'
jobObject, gradeObject = ESX.Jobs[job], ESX.Jobs[job].grades[grade]
end
userData.job.id = jobObject.id
userData.job.name = jobObject.name
userData.job.label = jobObject.label
userData.job.grade = tonumber(grade)
userData.job.grade_name = gradeObject.name
userData.job.grade_label = gradeObject.label
userData.job.grade_salary = gradeObject.salary
userData.job.skin_male = {}
userData.job.skin_female = {}
if gradeObject.skin_male then userData.job.skin_male = json.decode(gradeObject.skin_male) end
if gradeObject.skin_female then userData.job.skin_female = json.decode(gradeObject.skin_female) end
-- Inventory
if result[1].inventory and result[1].inventory ~= '' then
local inventory = json.decode(result[1].inventory)
for name,count in pairs(inventory) do
local item = ESX.Items[name]
if item then
foundItems[name] = count
else
print(('[^3WARNING^7] Ignoring invalid item "%s" for "%s"'):format(name, identifier))
end
end
end
for name,item in pairs(ESX.Items) do
local count = foundItems[name] or 0
if count > 0 then userData.weight = userData.weight + (item.weight * count) end
table.insert(userData.inventory, {
name = name,
count = count,
label = item.label,
weight = item.weight,
usable = ESX.UsableItemsCallbacks[name] ~= nil,
rare = item.rare,
canRemove = item.canRemove
})
end
table.sort(userData.inventory, function(a, b)
return a.label < b.label
end)
-- Group
if result[1].group then
if result[1].group == "superadmin" then
userData.group = "admin"
else
userData.group = result[1].group
end
else
userData.group = 'user'
end
-- Loadout
if result[1].loadout and result[1].loadout ~= '' then
local loadout = json.decode(result[1].loadout)
for name,weapon in pairs(loadout) do
local label = ESX.GetWeaponLabel(name)
if label then
if not weapon.components then weapon.components = {} end
if not weapon.tintIndex then weapon.tintIndex = 0 end
table.insert(userData.loadout, {
name = name,
ammo = weapon.ammo,
label = label,
components = weapon.components,
tintIndex = weapon.tintIndex
})
end
end
end
-- Position
if result[1].position and result[1].position ~= '' then
userData.coords = json.decode(result[1].position)
else
print('[^3WARNING^7] Column ^5"position"^0 in ^5"users"^0 table is missing required default value. Using backup coords, fix your database.')
userData.coords = {x = -269.4, y = -955.3, z = 31.2, heading = 205.8}
end
-- Skin
if result[1].skin and result[1].skin ~= '' then
userData.skin = json.decode(result[1].skin)
else
if userData.sex == 'f' then userData.skin = {sex=1} else userData.skin = {sex=0} end
end
-- Identity
if result[1].firstname and result[1].firstname ~= '' then
userData.firstname = result[1].firstname
userData.lastname = result[1].lastname
userData.playerName = userData.firstname..' '..userData.lastname
if result[1].dateofbirth then userData.dateofbirth = result[1].dateofbirth end
if result[1].sex then userData.sex = result[1].sex end
if result[1].height then userData.height = result[1].height end
end
cb()
end)
end)
Async.parallel(tasks, function(results)
local xPlayer = CreateExtendedPlayer(playerId, identifier, userData.group, userData.accounts, userData.inventory, userData.weight, userData.job, userData.loadout, userData.playerName, userData.coords)
ESX.Players[playerId] = xPlayer
if userData.firstname then
xPlayer.set('firstName', userData.firstname)
xPlayer.set('lastName', userData.lastname)
if userData.dateofbirth then xPlayer.set('dateofbirth', userData.dateofbirth) end
if userData.sex then xPlayer.set('sex', userData.sex) end
if userData.height then xPlayer.set('height', userData.height) end
for account,money in pairs(accounts) do
foundAccounts[account] = money
end
end
TriggerEvent('esx:playerLoaded', playerId, xPlayer, isNew)
for account,label in pairs(Config.Accounts) do
table.insert(userData.accounts, {
name = account,
money = foundAccounts[account] or Config.StartingAccountMoney[account] or 0,
label = label
})
end
xPlayer.triggerEvent('esx:playerLoaded', {
accounts = xPlayer.getAccounts(),
coords = xPlayer.getCoords(),
identifier = xPlayer.getIdentifier(),
inventory = xPlayer.getInventory(),
job = xPlayer.getJob(),
loadout = xPlayer.getLoadout(),
maxWeight = xPlayer.getMaxWeight(),
money = xPlayer.getMoney(),
dead = false
}, isNew, userData.skin)
-- Job
if ESX.DoesJobExist(job, grade) then
jobObject, gradeObject = ESX.Jobs[job], ESX.Jobs[job].grades[grade]
else
print(('[^3WARNING^7] Ignoring invalid job for %s [job: %s, grade: %s]'):format(identifier, job, grade))
job, grade = 'unemployed', '0'
jobObject, gradeObject = ESX.Jobs[job], ESX.Jobs[job].grades[grade]
end
xPlayer.triggerEvent('esx:createMissingPickups', ESX.Pickups)
xPlayer.triggerEvent('esx:registerSuggestions', ESX.RegisteredCommands)
print(('[^2INFO^0] Player ^5"%s" ^0has connected to the server. ID: ^5%s^7'):format(xPlayer.getName(), playerId))
userData.job.id = jobObject.id
userData.job.name = jobObject.name
userData.job.label = jobObject.label
userData.job.grade = tonumber(grade)
userData.job.grade_name = gradeObject.name
userData.job.grade_label = gradeObject.label
userData.job.grade_salary = gradeObject.salary
userData.job.skin_male = {}
userData.job.skin_female = {}
if gradeObject.skin_male then userData.job.skin_male = json.decode(gradeObject.skin_male) end
if gradeObject.skin_female then userData.job.skin_female = json.decode(gradeObject.skin_female) end
-- Inventory
if result.inventory and result.inventory ~= '' then
local inventory = json.decode(result.inventory)
for name,count in pairs(inventory) do
local item = ESX.Items[name]
if item then
foundItems[name] = count
else
print(('[^3WARNING^7] Ignoring invalid item "%s" for "%s"'):format(name, identifier))
end
end
end
for name,item in pairs(ESX.Items) do
local count = foundItems[name] or 0
if count > 0 then userData.weight = userData.weight + (item.weight * count) end
table.insert(userData.inventory, {
name = name,
count = count,
label = item.label,
weight = item.weight,
usable = Core.UsableItemsCallbacks[name] ~= nil,
rare = item.rare,
canRemove = item.canRemove
})
end
table.sort(userData.inventory, function(a, b)
return a.label < b.label
end)
-- Group
if result.group then
if result.group == "superadmin" then
userData.group = "admin"
else
userData.group = result.group
end
else
userData.group = 'user'
end
-- Loadout
if result.loadout and result.loadout ~= '' then
local loadout = json.decode(result.loadout)
for name,weapon in pairs(loadout) do
local label = ESX.GetWeaponLabel(name)
if label then
if not weapon.components then weapon.components = {} end
if not weapon.tintIndex then weapon.tintIndex = 0 end
table.insert(userData.loadout, {
name = name,
ammo = weapon.ammo,
label = label,
components = weapon.components,
tintIndex = weapon.tintIndex
})
end
end
end
-- Position
if result.position and result.position ~= '' then
userData.coords = json.decode(result.position)
else
print('[^3WARNING^7] Column ^5"position"^0 in ^5"users"^0 table is missing required default value. Using backup coords, fix your database.')
userData.coords = {x = -269.4, y = -955.3, z = 31.2, heading = 205.8}
end
-- Skin
if result.skin and result.skin ~= '' then
userData.skin = json.decode(result.skin)
else
if userData.sex == 'f' then userData.skin = {sex=1} else userData.skin = {sex=0} end
end
-- Identity
if result.firstname and result.firstname ~= '' then
userData.firstname = result.firstname
userData.lastname = result.lastname
userData.playerName = userData.firstname..' '..userData.lastname
if result.dateofbirth then userData.dateofbirth = result.dateofbirth end
if result.sex then userData.sex = result.sex end
if result.height then userData.height = result.height end
end
local xPlayer = CreateExtendedPlayer(playerId, identifier, userData.group, userData.accounts, userData.inventory, userData.weight, userData.job, userData.loadout, userData.playerName, userData.coords)
ESX.Players[playerId] = xPlayer
if userData.firstname then
xPlayer.set('firstName', userData.firstname)
xPlayer.set('lastName', userData.lastname)
if userData.dateofbirth then xPlayer.set('dateofbirth', userData.dateofbirth) end
if userData.sex then xPlayer.set('sex', userData.sex) end
if userData.height then xPlayer.set('height', userData.height) end
end
TriggerEvent('esx:playerLoaded', playerId, xPlayer, isNew)
xPlayer.triggerEvent('esx:playerLoaded', {
accounts = xPlayer.getAccounts(),
coords = xPlayer.getCoords(),
identifier = xPlayer.getIdentifier(),
inventory = xPlayer.getInventory(),
job = xPlayer.getJob(),
loadout = xPlayer.getLoadout(),
maxWeight = xPlayer.getMaxWeight(),
money = xPlayer.getMoney(),
dead = false
}, isNew, userData.skin)
xPlayer.triggerEvent('esx:createMissingPickups', Core.Pickups)
xPlayer.triggerEvent('esx:registerSuggestions', Core.RegisteredCommands)
print(('[^2INFO^0] Player ^5"%s" ^0has connected to the server. ID: ^5%s^7'):format(xPlayer.getName(), playerId))
end
AddEventHandler('chatMessage', function(playerId, author, message)
@@ -319,7 +296,7 @@ AddEventHandler('playerDropped', function(reason)
if xPlayer then
TriggerEvent('esx:playerDropped', playerId, reason)
ESX.SavePlayer(xPlayer, function()
Core.SavePlayer(xPlayer, function()
ESX.Players[playerId] = nil
end)
end
@@ -331,7 +308,7 @@ if Config.Multichar then
if xPlayer then
TriggerEvent('esx:playerDropped', playerId, reason)
ESX.SavePlayer(xPlayer, function()
Core.SavePlayer(xPlayer, function()
ESX.Players[playerId] = nil
end)
end
@@ -512,7 +489,7 @@ end)
RegisterNetEvent('esx:onPickup')
AddEventHandler('esx:onPickup', function(pickupId)
local pickup, xPlayer, success = ESX.Pickups[pickupId], ESX.GetPlayerFromId(source)
local pickup, xPlayer, success = Core.Pickups[pickupId], ESX.GetPlayerFromId(source)
if pickup then
if pickup.type == 'item_standard' then
@@ -540,7 +517,7 @@ AddEventHandler('esx:onPickup', function(pickupId)
end
if success then
ESX.Pickups[pickupId] = nil
Core.Pickups[pickupId] = nil
TriggerClientEvent('esx:removePickup', -1, pickupId)
end
end
@@ -559,6 +536,10 @@ ESX.RegisterServerCallback('esx:getPlayerData', function(source, cb)
})
end)
ESX.RegisterServerCallback('esx:isUserAdmin', function(source, cb)
cb(Core.IsPlayerAdmin(source))
end)
ESX.RegisterServerCallback('esx:getOtherPlayerData', function(source, cb, target)
local xPlayer = ESX.GetPlayerFromId(target)
@@ -592,7 +573,7 @@ AddEventHandler('txAdmin:events:scheduledRestart', function(eventData)
if eventData.secondsRemaining == 60 then
Citizen.CreateThread(function()
Citizen.Wait(50000)
ESX.SavePlayers()
Core.SavePlayers()
end)
end
end)
+2 -2
View File
@@ -1,5 +1,5 @@
{
"version": "legacy",
"commit" : "1.3.5",
"changelog": "\n- Base resources updated to use ESX Legacy improvements\n - Improved functionality for ESX.GetExtendedPlayers to return specific players only\n - "
"commit" : "1.4.2",
"changelog": "\n- Updated `Car` Command. Fixed some vulnerabilities. Fix SQL. Updated Commands."
}
+2 -2
View File
@@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
esx_identity
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
esx_identity Copyright (C) 2015-2021 Jérémie N'gadi
esx_identity Copyright (C) 2015-2022 Jérémie N'gadi
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
+1 -1
View File
@@ -44,7 +44,7 @@ start esx_identity
### License
esx_identity - rp characters
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program Is free software: you can redistribute it And/Or modify it under the terms Of the GNU General Public License As published by the Free Software Foundation, either version 3 Of the License, Or (at your option) any later version.
+6 -1
View File
@@ -27,7 +27,12 @@ if not Config.UseDeferrals then
function EnableGui(state)
SetNuiFocus(state, state)
guiEnabled = state
--[[ Citizen.CreateThread(function()
while true do
Citizen.Wait(20000) -- UNCOMMENT THIS METHOD IF YOU ARE EXPERIENCING ISSUES WITH THE UI ON LOCALHOST | IF YOU STILL EXPERIENCE ISSUES AFTER REMOVING COMMENTS, INCREASE THE TIME.
end
end)
]]--
SendNUIMessage({
type = "enableui",
enable = state
+3 -11
View File
@@ -10,23 +10,15 @@ shared_script '@es_extended/imports.lua'
server_scripts {
'@es_extended/locale.lua',
'@mysql-async/lib/MySQL.lua',
'locales/en.lua',
'locales/es.lua',
'locales/cs.lua',
'locales/pl.lua',
'locales/fi.lua',
'@oxmysql/lib/MySQL.lua',
'locales/*.lua',
'config.lua',
'server/main.lua'
}
client_scripts {
'@es_extended/locale.lua',
'locales/en.lua',
'locales/es.lua',
'locales/cs.lua',
'locales/pl.lua',
'locales/fi.lua',
'locales/*.lua',
'config.lua',
'client/main.lua'
}
+32 -80
View File
@@ -9,17 +9,16 @@ if Config.UseDeferrals then
Citizen.Wait(100)
if identifier then
MySQL.Async.fetchAll('SELECT firstname, lastname, dateofbirth, sex, height FROM users WHERE identifier = @identifier', {
['@identifier'] = identifier
}, function(result)
if result[1] then
if result[1].firstname then
MySQL.single('SELECT firstname, lastname, dateofbirth, sex, height FROM users WHERE identifier = ?', {identifier},
function(result)
if result then
if result.firstname then
playerIdentity[identifier] = {
firstName = result[1].firstname,
lastName = result[1].lastname,
dateOfBirth = result[1].dateofbirth,
sex = result[1].sex,
height = result[1].height
firstName = result.firstname,
lastName = result.lastname,
dateOfBirth = result.dateofbirth,
sex = result.sex,
height = result.height
}
deferrals.done()
@@ -107,17 +106,16 @@ elseif not Config.UseDeferrals then
Citizen.Wait(40)
if identifier then
MySQL.Async.fetchAll('SELECT firstname, lastname, dateofbirth, sex, height FROM users WHERE identifier = @identifier', {
['@identifier'] = identifier
}, function(result)
if result[1] then
if result[1].firstname then
MySQL.single('SELECT firstname, lastname, dateofbirth, sex, height FROM users WHERE identifier = ?', {identifier},
function(result)
if result then
if result.firstname then
playerIdentity[identifier] = {
firstName = result[1].firstname,
lastName = result[1].lastname,
dateOfBirth = result[1].dateofbirth,
sex = result[1].sex,
height = result[1].height
firstName = result.firstname,
lastName = result.lastname,
dateOfBirth = result.dateofbirth,
sex = result.sex,
height = result.height
}
alreadyRegistered[identifier] = true
@@ -225,17 +223,16 @@ elseif not Config.UseDeferrals then
end)
function checkIdentity(xPlayer)
MySQL.Async.fetchAll('SELECT firstname, lastname, dateofbirth, sex, height FROM users WHERE identifier = @identifier', {
['@identifier'] = xPlayer.identifier
}, function(result)
if result[1] then
if result[1].firstname then
MySQL.single('SELECT firstname, lastname, dateofbirth, sex, height FROM users WHERE identifier = ?', {identifier},
function(result)
if result then
if result.firstname then
playerIdentity[xPlayer.identifier] = {
firstName = result[1].firstname,
lastName = result[1].lastname,
dateOfBirth = result[1].dateofbirth,
sex = result[1].sex,
height = result[1].height
firstName = result.firstname,
lastName = result.lastname,
dateOfBirth = result.dateofbirth,
sex = result.sex,
height = result.height
}
alreadyRegistered[xPlayer.identifier] = true
@@ -284,7 +281,7 @@ if Config.EnableCommands then
ESX.RegisterCommand('chardel', 'user', function(xPlayer, args, showError)
if xPlayer and xPlayer.getName() then
if Config.UseDeferrals then
xPlayer.kick(_('deleted_identity'))
xPlayer.kick(_U('deleted_identity'))
Citizen.Wait(1500)
deleteIdentity(xPlayer)
xPlayer.showNotification(_U('deleted_character'))
@@ -367,61 +364,16 @@ function deleteIdentity(xPlayer)
end
function saveIdentityToDatabase(identifier, identity)
MySQL.Sync.execute('UPDATE users SET firstname = @firstname, lastname = @lastname, dateofbirth = @dateofbirth, sex = @sex, height = @height WHERE identifier = @identifier', {
['@identifier'] = identifier,
['@firstname'] = identity.firstName,
['@lastname'] = identity.lastName,
['@dateofbirth'] = identity.dateOfBirth,
['@sex'] = identity.sex,
['@height'] = identity.height
})
MySQL.update.await('UPDATE users SET firstname = ?, lastname = ?, dateofbirth = ?, sex = ?, height = ? WHERE identifier = ?', {identity.firstName, identity.lastName, identity.dateOfBirth, identity.sex, identity.height, identifier})
end
function deleteIdentityFromDatabase(xPlayer)
MySQL.Sync.execute('UPDATE users SET firstname = @firstname, lastname = @lastname, dateofbirth = @dateofbirth, sex = @sex, height = @height , skin = @skin WHERE identifier = @identifier', {
['@identifier'] = xPlayer.identifier,
['@firstname'] = NULL,
['@lastname'] = NULL,
['@dateofbirth'] = NULL,
['@sex'] = NULL,
['@height'] = NULL,
['@skin'] = NULL
})
MySQL.query.await('UPDATE users SET firstname = ?, lastname = ?, dateofbirth = ?, sex = ?, height = ?, skin = ? WHERE identifier = ?', {nil, nil, nil, nil, nil, nil, xPlayer.identifier})
if Config.FullCharDelete then
MySQL.Sync.execute('UPDATE addon_account_data SET money = 0 WHERE account_name = @account_name AND owner = @owner', {
['@account_name'] = 'bank_savings',
['@owner'] = xPlayer.identifier
})
MySQL.update.await('UPDATE addon_account_data SET money = 0 WHERE account_name IN (?) AND owner = ?', {{'bank_savings', 'caution'}, xPlayer.identifier})
MySQL.Sync.execute('UPDATE addon_account_data SET money = 0 WHERE account_name = @account_name AND owner = @owner', {
['@account_name'] = 'caution',
['@owner'] = xPlayer.identifier
})
MySQL.Sync.execute('UPDATE datastore_data SET data = @data WHERE name = @name AND owner = @owner', {
['@data'] = '\'{}\'',
['@name'] = 'user_ears',
['@owner'] = xPlayer.identifier
})
MySQL.Sync.execute('UPDATE datastore_data SET data = @data WHERE name = @name AND owner = @owner', {
['@data'] = '\'{}\'',
['@name'] = 'user_glasses',
['@owner'] = xPlayer.identifier
})
MySQL.Sync.execute('UPDATE datastore_data SET data = @data WHERE name = @name AND owner = @owner', {
['@data'] = '\'{}\'',
['@name'] = 'user_helmet',
['@owner'] = xPlayer.identifier
})
MySQL.Sync.execute('UPDATE datastore_data SET data = @data WHERE name = @name AND owner = @owner', {
['@data'] = '\'{}\'',
['@name'] = 'user_mask',
['@owner'] = xPlayer.identifier
})
MySQL.prepare.await('UPDATE datastore_data SET data = ? WHERE name IN (?) AND owner = ?', {'\'{}\'', {'user_ears', 'user_glasses', 'user_helmet', 'user_mask'}, xPlayer.identifier})
end
end
+2 -2
View File
@@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
esx_menu_default
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
esx_menu_default Copyright (C) 2015-2021 Jérémie N'gadi
esx_menu_default Copyright (C) 2015-2022 Jérémie N'gadi
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
+92 -94
View File
@@ -1,97 +1,95 @@
Citizen.CreateThread(function()
local ESX = exports['es_extended']:getSharedObject()
local GUI, MenuType = {}, 'default'
GUI.Time = 0
local ESX = exports.es_extended:getSharedObject()
local GUI, MenuType = {}, 'default'
GUI.Time = 0
local openMenu = function(namespace, name, data)
SendNUIMessage({
action = 'openMenu',
namespace = namespace,
name = name,
data = data
})
local openMenu = function(namespace, name, data)
SendNUIMessage({
action = 'openMenu',
namespace = namespace,
name = name,
data = data
})
end
local closeMenu = function(namespace, name)
SendNUIMessage({
action = 'closeMenu',
namespace = namespace,
name = name,
data = data
})
end
ESX.UI.Menu.RegisterType(MenuType, openMenu, closeMenu)
RegisterNUICallback('menu_submit', function(data, cb)
local menu = ESX.UI.Menu.GetOpened(MenuType, data._namespace, data._name)
if menu.submit ~= nil then
menu.submit(data, menu)
end
cb('OK')
end)
RegisterNUICallback('menu_cancel', function(data, cb)
local menu = ESX.UI.Menu.GetOpened(MenuType, data._namespace, data._name)
if menu.cancel ~= nil then
menu.cancel(data, menu)
end
cb('OK')
end)
RegisterNUICallback('menu_change', function(data, cb)
local menu = ESX.UI.Menu.GetOpened(MenuType, data._namespace, data._name)
for i=1, #data.elements, 1 do
menu.setElement(i, 'value', data.elements[i].value)
if data.elements[i].selected then
menu.setElement(i, 'selected', true)
else
menu.setElement(i, 'selected', false)
end
end
if menu.change ~= nil then
menu.change(data, menu)
end
cb('OK')
end)
Citizen.CreateThread(function()
while true do
Citizen.Wait(15)
if IsControlPressed(0, 18) and IsInputDisabled(0) and (GetGameTimer() - GUI.Time) > 150 then
SendNUIMessage({action = 'controlPressed', control = 'ENTER'})
GUI.Time = GetGameTimer()
end
if IsControlPressed(0, 177) and IsInputDisabled(0) and (GetGameTimer() - GUI.Time) > 150 then
SendNUIMessage({action = 'controlPressed', control = 'BACKSPACE'})
GUI.Time = GetGameTimer()
end
if IsControlPressed(0, 27) and IsInputDisabled(0) and (GetGameTimer() - GUI.Time) > 200 then
SendNUIMessage({action = 'controlPressed', control = 'TOP'})
GUI.Time = GetGameTimer()
end
if IsControlPressed(0, 173) and IsInputDisabled(0) and (GetGameTimer() - GUI.Time) > 200 then
SendNUIMessage({action = 'controlPressed', control = 'DOWN'})
GUI.Time = GetGameTimer()
end
if IsControlPressed(0, 174) and IsInputDisabled(0) and (GetGameTimer() - GUI.Time) > 150 then
SendNUIMessage({action = 'controlPressed', control = 'LEFT'})
GUI.Time = GetGameTimer()
end
if IsControlPressed(0, 175) and IsInputDisabled(0) and (GetGameTimer() - GUI.Time) > 150 then
SendNUIMessage({action = 'controlPressed', control = 'RIGHT'})
GUI.Time = GetGameTimer()
end
end
local closeMenu = function(namespace, name)
SendNUIMessage({
action = 'closeMenu',
namespace = namespace,
name = name,
data = data
})
end
ESX.UI.Menu.RegisterType(MenuType, openMenu, closeMenu)
RegisterNUICallback('menu_submit', function(data, cb)
local menu = ESX.UI.Menu.GetOpened(MenuType, data._namespace, data._name)
if menu.submit ~= nil then
menu.submit(data, menu)
end
cb('OK')
end)
RegisterNUICallback('menu_cancel', function(data, cb)
local menu = ESX.UI.Menu.GetOpened(MenuType, data._namespace, data._name)
if menu.cancel ~= nil then
menu.cancel(data, menu)
end
cb('OK')
end)
RegisterNUICallback('menu_change', function(data, cb)
local menu = ESX.UI.Menu.GetOpened(MenuType, data._namespace, data._name)
for i=1, #data.elements, 1 do
menu.setElement(i, 'value', data.elements[i].value)
if data.elements[i].selected then
menu.setElement(i, 'selected', true)
else
menu.setElement(i, 'selected', false)
end
end
if menu.change ~= nil then
menu.change(data, menu)
end
cb('OK')
end)
Citizen.CreateThread(function()
while true do
Citizen.Wait(15)
if IsControlPressed(0, 18) and IsInputDisabled(0) and (GetGameTimer() - GUI.Time) > 150 then
SendNUIMessage({action = 'controlPressed', control = 'ENTER'})
GUI.Time = GetGameTimer()
end
if IsControlPressed(0, 177) and IsInputDisabled(0) and (GetGameTimer() - GUI.Time) > 150 then
SendNUIMessage({action = 'controlPressed', control = 'BACKSPACE'})
GUI.Time = GetGameTimer()
end
if IsControlPressed(0, 27) and IsInputDisabled(0) and (GetGameTimer() - GUI.Time) > 200 then
SendNUIMessage({action = 'controlPressed', control = 'TOP'})
GUI.Time = GetGameTimer()
end
if IsControlPressed(0, 173) and IsInputDisabled(0) and (GetGameTimer() - GUI.Time) > 200 then
SendNUIMessage({action = 'controlPressed', control = 'DOWN'})
GUI.Time = GetGameTimer()
end
if IsControlPressed(0, 174) and IsInputDisabled(0) and (GetGameTimer() - GUI.Time) > 150 then
SendNUIMessage({action = 'controlPressed', control = 'LEFT'})
GUI.Time = GetGameTimer()
end
if IsControlPressed(0, 175) and IsInputDisabled(0) and (GetGameTimer() - GUI.Time) > 150 then
SendNUIMessage({action = 'controlPressed', control = 'RIGHT'})
GUI.Time = GetGameTimer()
end
end
end)
end)
+2 -2
View File
@@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
esx_menu_dialog
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
esx_menu_dialog Copyright (C) 2015-2021 Jérémie N'gadi
esx_menu_dialog Copyright (C) 2015-2022 Jérémie N'gadi
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
+1 -1
View File
@@ -29,7 +29,7 @@ start esx_menu_dialog
### License
esx_menu_dialog - input dialog for ESX
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program Is free software: you can redistribute it And/Or modify it under the terms Of the GNU General Public License As published by the Free Software Foundation, either version 3 Of the License, Or (at your option) any later version.
+98 -100
View File
@@ -1,105 +1,103 @@
local ESX = exports.es_extended:getSharedObject()
local Timeouts, OpenedMenus, MenuType = {}, {}, 'dialog'
local openMenu = function(namespace, name, data)
for i=1, #Timeouts, 1 do
ESX.ClearTimeout(Timeouts[i])
end
OpenedMenus[namespace .. '_' .. name] = true
SendNUIMessage({
action = 'openMenu',
namespace = namespace,
name = name,
data = data
})
local timeoutId = ESX.SetTimeout(200, function()
SetNuiFocus(true, true)
end)
table.insert(Timeouts, timeoutId)
end
local closeMenu = function(namespace, name)
OpenedMenus[namespace .. '_' .. name] = nil
SendNUIMessage({
action = 'closeMenu',
namespace = namespace,
name = name,
data = data
})
if ESX.Table.SizeOf(OpenedMenus) == 0 then
SetNuiFocus(false)
end
end
ESX.UI.Menu.RegisterType(MenuType, openMenu, closeMenu)
AddEventHandler('esx_menu_dialog:message:menu_submit', function(data)
local menu = ESX.UI.Menu.GetOpened(MenuType, data._namespace, data._name)
local cancel = false
if menu.submit then
-- is the submitted data a number?
if tonumber(data.value) then
data.value = ESX.Math.Round(tonumber(data.value))
-- check for negative value
if tonumber(data.value) <= 0 then
cancel = true
end
end
data.value = ESX.Math.Trim(data.value)
-- don't submit if the value is negative or if it's 0
if cancel then
ESX.ShowNotification('That input is not allowed!')
else
menu.submit(data, menu)
end
end
end)
AddEventHandler('esx_menu_dialog:message:menu_cancel', function(data)
local menu = ESX.UI.Menu.GetOpened(MenuType, data._namespace, data._name)
if menu.cancel ~= nil then
menu.cancel(data, menu)
end
end)
AddEventHandler('esx_menu_dialog:message:menu_change', function(data)
local menu = ESX.UI.Menu.GetOpened(MenuType, data._namespace, data._name)
if menu.change ~= nil then
menu.change(data, menu)
end
end)
Citizen.CreateThread(function()
local ESX = exports['es_extended']:getSharedObject()
local Timeouts, OpenedMenus, MenuType = {}, {}, 'dialog'
while true do
Citizen.Wait(10)
local openMenu = function(namespace, name, data)
for i=1, #Timeouts, 1 do
ESX.ClearTimeout(Timeouts[i])
if ESX.Table.SizeOf(OpenedMenus) > 0 then
DisableControlAction(0, 1, true) -- LookLeftRight
DisableControlAction(0, 2, true) -- LookUpDown
DisableControlAction(0, 142, true) -- MeleeAttackAlternate
DisableControlAction(0, 106, true) -- VehicleMouseControlOverride
DisableControlAction(0, 12, true) -- WeaponWheelUpDown
DisableControlAction(0, 14, true) -- WeaponWheelNext
DisableControlAction(0, 15, true) -- WeaponWheelPrev
DisableControlAction(0, 16, true) -- SelectNextWeapon
DisableControlAction(0, 17, true) -- SelectPrevWeapon
else
Citizen.Wait(500)
end
OpenedMenus[namespace .. '_' .. name] = true
SendNUIMessage({
action = 'openMenu',
namespace = namespace,
name = name,
data = data
})
local timeoutId = ESX.SetTimeout(200, function()
SetNuiFocus(true, true)
end)
table.insert(Timeouts, timeoutId)
end
local closeMenu = function(namespace, name)
OpenedMenus[namespace .. '_' .. name] = nil
SendNUIMessage({
action = 'closeMenu',
namespace = namespace,
name = name,
data = data
})
if ESX.Table.SizeOf(OpenedMenus) == 0 then
SetNuiFocus(false)
end
end
ESX.UI.Menu.RegisterType(MenuType, openMenu, closeMenu)
AddEventHandler('esx_menu_dialog:message:menu_submit', function(data)
local menu = ESX.UI.Menu.GetOpened(MenuType, data._namespace, data._name)
local cancel = false
if menu.submit then
-- is the submitted data a number?
if tonumber(data.value) then
data.value = ESX.Math.Round(tonumber(data.value))
-- check for negative value
if tonumber(data.value) <= 0 then
cancel = true
end
end
data.value = ESX.Math.Trim(data.value)
-- don't submit if the value is negative or if it's 0
if cancel then
ESX.ShowNotification('That input is not allowed!')
else
menu.submit(data, menu)
end
end
end)
AddEventHandler('esx_menu_dialog:message:menu_cancel', function(data)
local menu = ESX.UI.Menu.GetOpened(MenuType, data._namespace, data._name)
if menu.cancel ~= nil then
menu.cancel(data, menu)
end
end)
AddEventHandler('esx_menu_dialog:message:menu_change', function(data)
local menu = ESX.UI.Menu.GetOpened(MenuType, data._namespace, data._name)
if menu.change ~= nil then
menu.change(data, menu)
end
end)
Citizen.CreateThread(function()
while true do
Citizen.Wait(10)
if ESX.Table.SizeOf(OpenedMenus) > 0 then
DisableControlAction(0, 1, true) -- LookLeftRight
DisableControlAction(0, 2, true) -- LookUpDown
DisableControlAction(0, 142, true) -- MeleeAttackAlternate
DisableControlAction(0, 106, true) -- VehicleMouseControlOverride
DisableControlAction(0, 12, true) -- WeaponWheelUpDown
DisableControlAction(0, 14, true) -- WeaponWheelNext
DisableControlAction(0, 15, true) -- WeaponWheelPrev
DisableControlAction(0, 16, true) -- SelectNextWeapon
DisableControlAction(0, 17, true) -- SelectPrevWeapon
else
Citizen.Wait(500)
end
end
end)
end)
+2 -2
View File
@@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
esx_menu_list
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
esx_menu_list Copyright (C) 2015-2021 Jérémie N'gadi
esx_menu_list Copyright (C) 2015-2022 Jérémie N'gadi
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
+1 -1
View File
@@ -29,7 +29,7 @@ start esx_menu_list
### License
esx_menu_list - advanced menu inputs for ESX
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program Is free software: you can redistribute it And/Or modify it under the terms Of the GNU General Public License As published by the Free Software Foundation, either version 3 Of the License, Or (at your option) any later version.
+2 -2
View File
@@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
esx_skin
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
esx_skin Copyright (C) 2015-2021 Jérémie N'gadi
esx_skin Copyright (C) 2015-2022 Jérémie N'gadi
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
+1 -1
View File
@@ -32,7 +32,7 @@ start esx_skin
### License
esx_skin - skin selector for ESX
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program Is free software: you can redistribute it And/Or modify it under the terms Of the GNU General Public License As published by the Free Software Foundation, either version 3 Of the License, Or (at your option) any later version.
+1 -1
View File
@@ -9,7 +9,7 @@ version 'legacy'
shared_script '@es_extended/imports.lua'
server_scripts {
'@mysql-async/lib/MySQL.lua',
'@oxmysql/lib/MySQL.lua',
'@es_extended/locale.lua',
'locales/de.lua',
'locales/br.lua',
+2 -2
View File
@@ -10,7 +10,7 @@ AddEventHandler('esx_skin:save', function(skin)
xPlayer.setMaxWeight(defaultMaxWeight)
end
MySQL.Async.execute('UPDATE users SET skin = @skin WHERE identifier = @identifier', {
MySQL.update('UPDATE users SET skin = @skin WHERE identifier = @identifier', {
['@skin'] = json.encode(skin),
['@identifier'] = xPlayer.identifier
})
@@ -34,7 +34,7 @@ end)
ESX.RegisterServerCallback('esx_skin:getPlayerSkin', function(source, cb)
local xPlayer = ESX.GetPlayerFromId(source)
MySQL.Async.fetchAll('SELECT skin FROM users WHERE identifier = @identifier', {
MySQL.query('SELECT skin FROM users WHERE identifier = @identifier', {
['@identifier'] = xPlayer.identifier
}, function(users)
local user, skin = users[1]
+2 -2
View File
@@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
skinchanger
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
skinchanger Copyright (C) 2015-2021 Jérémie N'gadi
skinchanger Copyright (C) 2015-2022 Jérémie N'gadi
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
+1 -1
View File
@@ -94,7 +94,7 @@ end)
### License
skinchanger - make your own skin!
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program Is free software: you can redistribute it And/Or modify it under the terms Of the GNU General Public License As published by the Free Software Foundation, either version 3 Of the License, Or (at your option) any later version.
+2 -2
View File
@@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
esx_accessories
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
esx_accessories Copyright (C) 2015-2021 Jérémie N'gadi
esx_accessories Copyright (C) 2015-2022 Jérémie N'gadi
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
+1 -1
View File
@@ -37,7 +37,7 @@ start esx_accessories
### License
esx_accessories - buy some shiny stuff!
Copyright (C) 2015-2021 Lenaic Corbeau
Copyright (C) 2015-2022Lenaic Corbeau
This program Is free software: you can redistribute it And/Or modify it under the terms Of the GNU General Public License As published by the Free Software Foundation, either version 3 Of the License, Or (at your option) any later version.
@@ -18,6 +18,7 @@ server_scripts {
'locales/sv.lua',
'locales/cs.lua',
'locales/pl.lua',
'locales/hu.lua',
'config.lua',
'server/main.lua'
}
@@ -32,6 +33,7 @@ client_scripts {
'locales/sv.lua',
'locales/cs.lua',
'locales/pl.lua',
'locales/hu.lua',
'config.lua',
'client/main.lua'
}
@@ -0,0 +1,19 @@
Locales ['hu'] = {
['valid_purchase'] = 'Biztosan megveszed?',
['yes'] = 'Igen (<span style="color: green;">$%s</span>)',
['no'] = 'Nem',
['helmet'] = 'sisak / kalap',
['glasses'] = 'szemüveg',
['mask'] = 'maszk',
['ears'] = 'fül tartozékok',
['shop'] = '%s bolt',
['set_unset'] = 'Felvenni / Levenni',
['not_enough_money'] = 'Nincsen elég pénzed',
['press_access'] = 'Nyomj ~INPUT_CONTEXT~ hogy megnyisd a kiegészítöket',
['accessories_blip'] = 'Kiegészítők',
['no_ears'] = 'Nincsen fülbevalód',
['no_glasses'] = 'Nincsen szemüveged',
['no_helmet'] = 'Nincsen sapkád',
['no_mask'] = 'Nincsen maszkod',
['you_paid'] = 'Fizettél ~g~$%s~s~',
}
+2 -2
View File
@@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
esx_addonaccount
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
esx_addonaccount Copyright (C) 2015-2021 Jérémie N'gadi
esx_addonaccount Copyright (C) 2015-2022 Jérémie N'gadi
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
+1 -1
View File
@@ -52,7 +52,7 @@ end)
### License
esx_addonaccount - addon account for ESX
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program Is free software: you can redistribute it And/Or modify it under the terms Of the GNU General Public License As published by the Free Software Foundation, either version 3 Of the License, Or (at your option) any later version.
+1 -1
View File
@@ -8,7 +8,7 @@ version 'legacy'
server_scripts {
'@es_extended/imports.lua',
'@mysql-async/lib/MySQL.lua',
'@oxmysql/lib/MySQL.lua',
'server/classes/addonaccount.lua',
'server/main.lua'
}
@@ -8,37 +8,25 @@ function CreateAddonAccount(name, owner, money)
self.addMoney = function(m)
self.money = self.money + m
self.save()
TriggerClientEvent('esx_addonaccount:setMoney', -1, self.name, self.money)
end
self.removeMoney = function(m)
self.money = self.money - m
self.save()
TriggerClientEvent('esx_addonaccount:setMoney', -1, self.name, self.money)
end
self.setMoney = function(m)
self.money = m
self.save()
TriggerClientEvent('esx_addonaccount:setMoney', -1, self.name, self.money)
end
self.save = function()
if self.owner == nil then
MySQL.Async.execute('UPDATE addon_account_data SET money = @money WHERE account_name = @account_name', {
['@account_name'] = self.name,
['@money'] = self.money
})
MySQL.update('UPDATE addon_account_data SET money = ? WHERE account_name = ?', {self.money, self.name})
else
MySQL.Async.execute('UPDATE addon_account_data SET money = @money WHERE account_name = @account_name AND owner = @owner', {
['@account_name'] = self.name,
['@money'] = self.money,
['@owner'] = self.owner
})
MySQL.update('UPDATE addon_account_data SET money = ? WHERE account_name = ? AND owner = ?', {self.money, self.name, self.owner})
end
TriggerClientEvent('esx_addonaccount:setMoney', -1, self.name, self.money)
end
return self
+27 -39
View File
@@ -1,41 +1,33 @@
local AccountsIndex, Accounts, SharedAccounts = {}, {}, {}
MySQL.ready(function()
local result = MySQL.Sync.fetchAll('SELECT * FROM addon_account')
AddEventHandler('onResourceStart', function(resourceName)
if resourceName == GetCurrentResourceName() then
local accounts = MySQL.query.await('SELECT * FROM addon_account LEFT JOIN addon_account_data ON addon_account.name = addon_account_data.account_name UNION SELECT * FROM addon_account RIGHT JOIN addon_account_data ON addon_account.name = addon_account_data.account_name')
for i=1, #result, 1 do
local name = result[i].name
local label = result[i].label
local shared = result[i].shared
local result2 = MySQL.Sync.fetchAll('SELECT * FROM addon_account_data WHERE account_name = @account_name', {
['@account_name'] = name
})
if shared == 0 then
table.insert(AccountsIndex, name)
Accounts[name] = {}
for j=1, #result2, 1 do
local addonAccount = CreateAddonAccount(name, result2[j].owner, result2[j].money)
table.insert(Accounts[name], addonAccount)
end
else
local money = nil
if #result2 == 0 then
MySQL.Sync.execute('INSERT INTO addon_account_data (account_name, money, owner) VALUES (@account_name, @money, NULL)', {
['@account_name'] = name,
['@money'] = 0
})
money = 0
local newAccounts = {}
for i = 1, #accounts do
local account = accounts[i]
if account.shared == 0 then
if not Accounts[account.name] then
AccountsIndex[#AccountsIndex + 1] = account.name
Accounts[account.name] = {}
end
Accounts[account.name][#Accounts[account.name] + 1] = CreateAddonAccount(account.name, account.owner, account.money)
else
money = result2[1].money
if account.money then
SharedAccounts[account.name] = CreateAddonAccount(account.name, nil, account.money)
else
newAccounts[#newAccounts + 1] = {account.name, 0}
end
end
end
local addonAccount = CreateAddonAccount(name, nil, money)
SharedAccounts[name] = addonAccount
if next(newAccounts) then
MySQL.prepare('INSERT INTO addon_account_data (account_name, money) VALUES (?, ?)', newAccounts)
for i = 1, #newAccounts do
local newAccount = newAccounts[i]
SharedAccounts[newAccount[1]] = CreateAddonAccount(newAccount[1], nil, 0)
end
end
end
end)
@@ -68,17 +60,13 @@ AddEventHandler('esx:playerLoaded', function(playerId, xPlayer)
local account = GetAccount(name, xPlayer.identifier)
if account == nil then
MySQL.Async.execute('INSERT INTO addon_account_data (account_name, money, owner) VALUES (@account_name, @money, @owner)', {
['@account_name'] = name,
['@money'] = 0,
['@owner'] = xPlayer.identifier
})
MySQL.insert('INSERT INTO addon_account_data (account_name, money, owner) VALUES (?, ?, ?)', {name, 0, xPlayer.identifier})
account = CreateAddonAccount(name, xPlayer.identifier, 0)
table.insert(Accounts[name], account)
Accounts[name][#Accounts[name] + 1] = account
end
table.insert(addonAccounts, account)
addonAccounts[#addonAccounts + 1] = account
end
xPlayer.set('addonAccounts', addonAccounts)
+2 -2
View File
@@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
esx_addoninventory
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
esx_addoninventory Copyright (C) 2015-2021 Jérémie N'gadi
esx_addoninventory Copyright (C) 2015-2022 Jérémie N'gadi
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
+1 -1
View File
@@ -52,7 +52,7 @@ end)
### License
esx_addoninventory - inventories!
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program Is free software: you can redistribute it And/Or modify it under the terms Of the GNU General Public License As published by the Free Software Foundation, either version 3 Of the License, Or (at your option) any later version.
@@ -8,7 +8,7 @@ version 'legacy'
server_scripts {
'@es_extended/imports.lua',
'@mysql-async/lib/MySQL.lua',
'@oxmysql/lib/MySQL.lua',
'server/classes/addoninventory.lua',
'server/main.lua'
}
@@ -42,14 +42,14 @@ function CreateAddonInventory(name, owner, items)
table.insert(self.items, item)
if self.owner == nil then
MySQL.Async.execute('INSERT INTO addon_inventory_items (inventory_name, name, count) VALUES (@inventory_name, @item_name, @count)',
MySQL.update('INSERT INTO addon_inventory_items (inventory_name, name, count) VALUES (@inventory_name, @item_name, @count)',
{
['@inventory_name'] = self.name,
['@item_name'] = name,
['@count'] = 0
})
else
MySQL.Async.execute('INSERT INTO addon_inventory_items (inventory_name, name, count, owner) VALUES (@inventory_name, @item_name, @count, @owner)',
MySQL.update('INSERT INTO addon_inventory_items (inventory_name, name, count, owner) VALUES (@inventory_name, @item_name, @count, @owner)',
{
['@inventory_name'] = self.name,
['@item_name'] = name,
@@ -63,13 +63,13 @@ function CreateAddonInventory(name, owner, items)
self.saveItem = function(name, count)
if self.owner == nil then
MySQL.Async.execute('UPDATE addon_inventory_items SET count = @count WHERE inventory_name = @inventory_name AND name = @item_name', {
MySQL.update('UPDATE addon_inventory_items SET count = @count WHERE inventory_name = @inventory_name AND name = @item_name', {
['@inventory_name'] = self.name,
['@item_name'] = name,
['@count'] = count
})
else
MySQL.Async.execute('UPDATE addon_inventory_items SET count = @count WHERE inventory_name = @inventory_name AND name = @item_name AND owner = @owner', {
MySQL.update('UPDATE addon_inventory_items SET count = @count WHERE inventory_name = @inventory_name AND name = @item_name AND owner = @owner', {
['@inventory_name'] = self.name,
['@item_name'] = name,
['@count'] = count,
@@ -2,20 +2,20 @@ Items = {}
local InventoriesIndex, Inventories, SharedInventories = {}, {}, {}
MySQL.ready(function()
local items = MySQL.Sync.fetchAll('SELECT * FROM items')
local items = MySQL.query.await('SELECT * FROM items')
for i=1, #items, 1 do
Items[items[i].name] = items[i].label
end
local result = MySQL.Sync.fetchAll('SELECT * FROM addon_inventory')
local result = MySQL.query.await('SELECT * FROM addon_inventory')
for i=1, #result, 1 do
local name = result[i].name
local label = result[i].label
local shared = result[i].shared
local result2 = MySQL.Sync.fetchAll('SELECT * FROM addon_inventory_items WHERE inventory_name = @inventory_name', {
local result2 = MySQL.query.await('SELECT * FROM addon_inventory_items WHERE inventory_name = @inventory_name', {
['@inventory_name'] = name
})
+2 -2
View File
@@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
esx_ambulancejob
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
esx_ambulancejob Copyright (C) 2015-2021 Jérémie N'gadi
esx_ambulancejob Copyright (C) 2015-2022 Jérémie N'gadi
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
+1 -1
View File
@@ -44,7 +44,7 @@ start esx_ambulancejob
### License
esx_ambulancejob - ambulance script for fivem
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program Is free software: you can redistribute it And/Or modify it under the terms Of the GNU General Public License As published by the Free Software Foundation, either version 3 Of the License, Or (at your option) any later version.
@@ -26,14 +26,14 @@ AddEventHandler('esx:onPlayerSpawn', function()
if firstSpawn then
firstSpawn = false
if Config.AntiCombatLog then
if Config.SaveDeathStatus then
while not ESX.PlayerLoaded do
Citizen.Wait(1000)
end
ESX.TriggerServerCallback('esx_ambulancejob:getDeathStatus', function(shouldDie)
if shouldDie then
Citizen.Wait(5000)
Citizen.Wait(1000)
SetEntityHealth(PlayerPedId(), 0)
end
end)
@@ -109,17 +109,17 @@ function OpenVehicleSpawnerMenu(type, hospital, part, partNum)
end
function StoreNearbyVehicle(playerCoords)
local vehicles, vehiclePlates = ESX.Game.GetVehiclesInArea(playerCoords, 30.0), {}
if #vehicles > 0 then
for k,v in ipairs(vehicles) do
local vehicles, plates, index = ESX.Game.GetVehiclesInArea(playerCoords, 30.0), {}, {}
if next(vehicles) then
for i = 1, #vehicles do
local vehicle = vehicles[i]
-- Make sure the vehicle we're saving is empty, or else it wont be deleted
if GetVehicleNumberOfPassengers(v) == 0 and IsVehicleSeatFree(v, -1) then
table.insert(vehiclePlates, {
vehicle = v,
plate = ESX.Math.Trim(GetVehicleNumberPlateText(v))
})
if GetVehicleNumberOfPassengers(vehicle) == 0 and IsVehicleSeatFree(vehicle, -1) then
local plate = ESX.Math.Trim(GetVehicleNumberPlateText(vehicle))
plates[#plates + 1] = plate
index[plate] = vehicle
end
end
else
@@ -127,11 +127,11 @@ function StoreNearbyVehicle(playerCoords)
return
end
ESX.TriggerServerCallback('esx_ambulancejob:storeNearbyVehicle', function(storeSuccess, foundNum)
if storeSuccess then
local vehicleId = vehiclePlates[foundNum]
ESX.TriggerServerCallback('esx_ambulancejob:storeNearbyVehicle', function(plate)
if plate then
local vehicleId = index[plate]
local attempts = 0
ESX.Game.DeleteVehicle(vehicleId.vehicle)
ESX.Game.DeleteVehicle(vehicleId)
isBusy = true
Citizen.CreateThread(function()
@@ -142,7 +142,7 @@ function StoreNearbyVehicle(playerCoords)
end)
-- Workaround for vehicle not deleting when other players are near it.
while DoesEntityExist(vehicleId.vehicle) do
while DoesEntityExist(vehicleId) do
Citizen.Wait(500)
attempts = attempts + 1
@@ -153,9 +153,10 @@ function StoreNearbyVehicle(playerCoords)
vehicles = ESX.Game.GetVehiclesInArea(playerCoords, 30.0)
if #vehicles > 0 then
for k,v in ipairs(vehicles) do
if ESX.Math.Trim(GetVehicleNumberPlateText(v)) == vehicleId.plate then
ESX.Game.DeleteVehicle(v)
for i = 1, #vehicles do
local vehicle = vehicles[i]
if ESX.Math.Trim(GetVehicleNumberPlateText(vehicle)) == plate then
ESX.Game.DeleteVehicle(vehicle)
break
end
end
@@ -167,7 +168,7 @@ function StoreNearbyVehicle(playerCoords)
else
ESX.ShowNotification(_U('garage_has_notstored'))
end
end, vehiclePlates)
end, plates)
end
function GetAvailableVehicleSpawnPoint(hospital, part, partNum)
+1 -1
View File
@@ -5,7 +5,7 @@ Config.DrawDistance = 20.0 -- How close do you need to be in order
Config.Marker = {type = 1, x = 1.5, y = 1.5, z = 0.5, r = 102, g = 0, b = 102, a = 100, rotate = false}
Config.ReviveReward = 700 -- Revive reward, set to 0 if you don't want it enabled
Config.AntiCombatLog = true -- Enable anti-combat logging? (Removes Items when a player logs back after intentionally logging out while dead.)
Config.SaveDeathStatus = true -- Save Death Status?
Config.LoadIpl = true -- Disable if you're using fivem-ipl or other IPL loaders
Config.Locale = 'en'
+3 -1
View File
@@ -9,7 +9,7 @@ version 'legacy'
shared_script '@es_extended/imports.lua'
server_scripts {
'@mysql-async/lib/MySQL.lua',
'@oxmysql/lib/MySQL.lua',
'@es_extended/locale.lua',
'locales/br.lua',
'locales/en.lua',
@@ -22,6 +22,7 @@ server_scripts {
'locales/cs.lua',
'locales/nl.lua',
'locales/tr.lua',
'locales/hu.lua',
'config.lua',
'server/main.lua'
}
@@ -38,6 +39,7 @@ client_scripts {
'locales/cs.lua',
'locales/nl.lua',
'locales/tr.lua',
'locales/hu.lua',
'config.lua',
'client/main.lua',
'client/job.lua',
+1 -1
View File
@@ -71,7 +71,7 @@ Locales['br'] = {
['respawn_bleedout_fine_msg'] = 'você precisa pagar ~r~$%s~s~ para reviver',
['distress_send'] = 'pressione [~b~G~s~] enviar sinal de socorro',
['distress_sent'] = 'sinal de socorro foi enviado para as unidades disponíveis!',
['combatlog_message'] = 'você foi revivido porque deixou o servidor anteriormente quando estava morto.',
-- Revive
['revive_help'] = 'reviver um cidadão',
-- Item
@@ -71,7 +71,6 @@ Locales['cs'] = {
['respawn_bleedout_fine_msg'] = 'zaplatili jste ~r~$%s~s~ za respawn.',
['distress_send'] = 'stiskněte [~b~G~s~] pro vyslání tísňového signálu',
['distress_sent'] = 'tísňový signál byl vyslán dostupným jednotkám!',
['combatlog_message'] = 'byli jste násilně oživeni, protože jste předtím opustili server, když jste byli mrtví.',
-- Revive
['revive_help'] = 'oživit hráče',
-- Item
@@ -70,7 +70,6 @@ Locales['de'] = {
['respawn_bleedout_fine_msg'] = 'Du hast ~r~$%s~s~ bezahlt, um zu respawnen.',
['distress_send'] = 'Drücke [~b~G~s~] um ein Notsignal zu senden',
['distress_sent'] = 'Notsignal wurde an den Rettungsdienst übermittelt!',
['combatlog_message'] = 'Du wurdest respawnt, da du den Server verlassen hast, als du gestorben bist.',
-- Revive
['revive_help'] = 'Belebe einen Spieler wieder',
-- Item
@@ -71,7 +71,6 @@ Locales['en'] = {
['respawn_bleedout_fine_msg'] = 'you paid ~r~$%s~s~ to respawn.',
['distress_send'] = 'press [~b~G~s~] to send distress signal',
['distress_sent'] = 'distress signal has been sent to available units!',
['combatlog_message'] = 'you have been force-respawned because you\'ve previously left the server when dead.',
-- Revive
['revive_help'] = 'revive a player',
-- Item
+1 -1
View File
@@ -73,7 +73,7 @@ Locales['es'] = {
['respawn_bleedout_fine_msg'] = 'Tu pagaste ~r~$%s~s~ para reaparecer.',
['distress_send'] = 'Presiona [~b~G~s~] para enviar señal de socorro',
['distress_sent'] = 'Se ha enviado una señal de socorro a las unidades disponibles.',
['combatlog_message'] = 'Ha sido reaparecido a la fuerza porque anteriormente abandonó el servidor cuando estaba muerto.',
-- Revive
['revive_help'] = 'Revivir un jugador',
-- Item
@@ -71,7 +71,6 @@ Locales['fi'] = {
['respawn_bleedout_fine_msg'] = 'you paid ~r~$%s~s~ to respawn.',
['distress_send'] = 'press [~b~G~s~] to send distress signal',
['distress_sent'] = 'distress signal has been sent to available units!',
['combatlog_message'] = 'you have been force-respawned because you\'ve previously left the server when dead.',
-- Revive
['revive_help'] = 'elvytä pelaaja',
-- Item
@@ -71,7 +71,6 @@ Locales['fr'] = {
['respawn_bleedout_fine_msg'] = 'vous avez payé ~r~$%s~s~ pour être réanimer.',
['distress_send'] = 'appuyez sur [~b~G~s~] pour envoyer un signal de détresse',
['distress_sent'] = 'un signal a été envoyé à toutes les unités disponibles!',
['combatlog_message'] = 'vous avez été réanimé de force car vous avez quitté le serveur.',
-- Revive
['revive_help'] = 'relancer un joueur',
-- Item
@@ -0,0 +1,85 @@
Locales['hu'] = {
-- Cloakroom
['cloakroom'] = 'Öltöző',
['ems_clothes_civil'] = 'Civil ruházat',
['ems_clothes_ems'] = 'Munkaruha',
-- Vehicles
['ambulance'] = 'Mentőautó',
['helicopter_prompt'] = '~b~[Információ]:~s~ Nyomd meg az ~INPUT_CONTEXT~ gombot a helikopter listához.',
['garage_prompt'] = '~b~[Információ]:~s~ Nyomd meg az ~INPUT_CONTEXT~ gombot a kocsi listához.',
['garage_title'] = 'Autó funkciók',
['garage_stored'] = 'Garázsba',
['garage_notstored'] = 'Ismeretlen helyen',
['garage_storing'] = 'Próbáljuk betteni a kocsid a garázsodba, de előtte nézz körül, hogy biztos nincs melletted senki',
['garage_has_stored'] = '~b~[Információ]:~s~ Sikeresen tároltad a garázsba!',
['garage_has_notstored'] = '~r~[Információ]:~s~ Nincs a közeledben semmi!',
['garage_notavailable'] = '~r~[Információ]:~s~ Nem tárolhatod a garázsba!',
['garage_blocked'] = '~r~[Információ]:~s~ Valami gátolja a kocsi lehívását!',
['garage_empty'] = '~r~[Információ]:~s~ Nem teheted a garázsba!',
['garage_released'] = '~b~[Információ]:~s~ Sikeresen kivetted!',
['garage_store_nearby'] = '~r~[Információ]:~s~ Nincs a közeledben semmi!',
['garage_storeditem'] = 'Garázs megnyitása',
['garage_storeitem'] = 'Kocsi berakása a garázsba',
['garage_buyitem'] = 'Kocsi igénylés',
['shop_item'] = '$%s',
['vehicleshop_title'] = 'Autókereskedés',
['vehicleshop_confirm'] = 'Megszeretnéd venni ezt a járművet?',
['vehicleshop_bought'] = '~b~[Információ]:~s~ Sikeresen igényeltél egy ~b~%s~s~ ennyiért: ~r~%s~s~$',
['vehicleshop_money'] = '~r~[Információ]:~s~ Ezt most nem tudod megtenni!',
['vehicleshop_awaiting_model'] = 'Betöltés..',
['confirm_no'] = 'Vissza',
['confirm_yes'] = 'Igényel',
-- Action Menu
['revive_inprogress'] = '~b~[Információ]:~s~ Elkezdted az újraélesztést!',
['revive_complete'] = '~b~[Információ]:~s~ Újraélesztetted: ~b~%s~s~',
['revive_complete_award'] = '~b~[Információ]:~s~ Újraélesztetted: ~b~%s~s~ játékost.',
['revive_fail_offline'] = 'A játékos nem elérhető',
['heal_inprogress'] = '~b~[Információ]:~s~ Elkezdted a gyógyítást!',
['heal_complete'] = '~b~[Információ]:~s~ Meggyógyítottad: ~b~%s~s~ játékost.',
['no_players'] = '~r~[Információ]:~s~ Nincs a közeledben senki!',
['player_not_unconscious'] = '~b~[Információ]:~s~ A játékos nincs öntudatánál!',
['player_not_conscious'] = '~b~[Információ]:~s~ A játékos nincs öntudatánál!',
-- Boss Menu
['boss_actions'] = 'Leader panel',
-- Misc
['invalid_amount'] = '~r~Érvénytelen mennyiség',
['actions_prompt'] = '~b~[Információ]:~s~ Nyomd meg az ~INPUT_CONTEXT~ gombot a panel megnyitásához.',
['deposit_amount'] = 'Összeg betétele',
['money_withdraw'] = 'Összeg kivétele',
['fast_travel'] = 'Nyomj ~INPUT_CONTEXT~ hogy használd a liftet',
['open_pharmacy'] = '~b~[Információ]:~s~ Nyomd meg az ~INPUT_CONTEXT~ gombot a gyógyszer kivételéhez.',
['pharmacy_menu_title'] = 'Kellékek',
['pharmacy_take'] = 'Kivétel: <span style="color:red;">%s</span>',
['medikit'] = 'Elsősegély készlet',
['bandage'] = 'Kötszer',
['max_item'] = '~r~[Információ]:~s~ Nem fér már el nálad!',
-- F6 Menu
['ems_menu'] = 'EMS menü',
['ems_menu_title'] = 'EMS Menu',
['ems_menu_revive'] = 'Újraélesztés',
['ems_menu_putincar'] = 'Jármübe rakás',
['ems_menu_small'] = 'Kis sebek meggyógyítása',
['ems_menu_big'] = 'Súlyos sérülések kezelése',
['ems_menu_search'] = 'Civil megkeresése',
-- Phone
['alert_ambulance'] = 'EMS értesités',
-- Death
['respawn_available_in'] = 'Újraéledés: ~r~%s : %s',
['respawn_bleedout_in'] = 'Elfogsz vérezni ~b~%s perc %s másodperc~s~ múlva...\n',
['respawn_bleedout_prompt'] = 'Nyomd meg az ~b~[E]~s~ gombot az újraéledéshez',
['respawn_bleedout_fine'] = 'Újraéledéshez: ~b~[E]~s~',
['respawn_bleedout_fine_msg'] = '~b~[Információ]:Ennyit fizettél ~r~$%s~s~, hogy újraéledj',
['distress_send'] = 'Nyomd meg a ~r~[G]~s~ gombot a segítségkéréshez',
['distress_sent'] = '~b~[Információ]:~s~ Egy civil értesítette az illetékes szervezetet!',
-- Revive
['revive_help'] = 'újraéleszteni egy játékos',
-- Item
['used_medikit'] = '~b~[Információ]:~s~ Elhasználtál ~b~1x Segélytáskát~s~.',
['used_bandage'] = '~b~[Információ]:~s~ Elhasználtál ~b~1x Kötszert~s~.',
['not_enough_medikit'] = '~r~[Információ]:~s~ Nincs nálad: ~b~Defibrillátor~s~.',
['not_enough_bandage'] = '~r~[Információ]:~s~ Nincs nálad: ~b~Kötszer~s~.',
['healed'] = '~b~[Információ]:~s~ Meggyógyítottak!',
-- Blips
['blip_hospital'] = 'Korház',
['blip_dead'] = 'Eszméletlen játékos',
}
@@ -70,7 +70,6 @@ Locales['nl'] = {
['respawn_bleedout_fine_msg'] = 'Je hebt ~r~€%s~s~ betaald om te respawnen.',
['distress_send'] = 'Druk op [~b~G~s~] om een noodsignaal te verzenden',
['distress_sent'] = 'Noodsignaal verzonden naar alle beschikbare eenheden!',
['combatlog_message'] = 'Je bent gerespawned omdat je uitgelogt bent terwijl je dood was.',
-- Revive
['revive_help'] = 'Revive een speler',
-- Item
@@ -71,7 +71,6 @@ Locales['pl'] = {
['respawn_bleedout_fine_msg'] = 'you paid ~r~$%s~s~ to respawn.',
['distress_send'] = 'press [~b~G~s~] to send distress signal',
['distress_sent'] = 'distress signal has been sent to available units!',
['combatlog_message'] = 'you have been force-respawned because you\'ve previously left the server when dead.',
-- Revive
['revive_help'] = 'ożyw gracza',
-- Item
@@ -71,7 +71,6 @@ Locales['sv'] = {
['respawn_bleedout_fine_msg'] = 'du betalade ~r~%s SEK~s~ för att respawna.',
['distress_send'] = 'tryck ~b~[G]~s~ för att skicka nödsignal',
['distress_sent'] = 'nödsignal har skickats till samtliga enheter!',
['combatlog_message'] = 'du har force-respawnats på grund av att du lämnat servern medans du var död',
-- Revive
['revive_help'] = 'återuppliva en spelare',
-- Item
@@ -70,8 +70,6 @@ Locales['tr'] = {
['respawn_bleedout_fine_msg'] = 'yeniden doğmak için ~r~$%s~s~ ödediniz.',
['distress_send'] = 'acile sinyal göndermek için [~b~G~s~] basın',
['distress_sent'] = 'acil durum sinyali gönderildi!',
['combatlog_message'] = 'daha önce öldüğünüzde sunucudan ayrıldığınız için zorunlu olarak yeniden doğdunuz.',
-- Revive
['revive_help'] = 'oyuncuyu canlandır',
-- Item
['used_medikit'] = '~y~1x~s~ sağlık kiti kullanıldı.',
+27 -47
View File
@@ -178,14 +178,8 @@ ESX.RegisterServerCallback('esx_ambulancejob:buyJobVehicle', function(source, cb
if xPlayer.getMoney() >= price then
xPlayer.removeMoney(price)
MySQL.Async.execute('INSERT INTO owned_vehicles (owner, vehicle, plate, type, job, `stored`) VALUES (@owner, @vehicle, @plate, @type, @job, @stored)', {
['@owner'] = xPlayer.identifier,
['@vehicle'] = json.encode(vehicleProps),
['@plate'] = vehicleProps.plate,
['@type'] = type,
['@job'] = xPlayer.job.name,
['@stored'] = true
}, function (rowsChanged)
MySQL.insert('INSERT INTO owned_vehicles (owner, vehicle, plate, type, job, `stored`) VALUES (?, ?, ?, ?, ?, ?)', {xPlayer.identifier, json.encode(vehicleProps), vehicleProps.plate, type, xPlayer.job.name, true},
function (rowsChanged)
cb(true)
end)
else
@@ -194,46 +188,32 @@ ESX.RegisterServerCallback('esx_ambulancejob:buyJobVehicle', function(source, cb
end
end)
ESX.RegisterServerCallback('esx_ambulancejob:storeNearbyVehicle', function(source, cb, nearbyVehicles)
ESX.RegisterServerCallback('esx_ambulancejob:storeNearbyVehicle', function(source, cb, plates)
local xPlayer = ESX.GetPlayerFromId(source)
local foundPlate, foundNum
for k,v in ipairs(nearbyVehicles) do
local result = MySQL.Sync.fetchAll('SELECT plate FROM owned_vehicles WHERE owner = @owner AND plate = @plate AND job = @job', {
['@owner'] = xPlayer.identifier,
['@plate'] = v.plate,
['@job'] = xPlayer.job.name
})
local plate = MySQL.scalar.await('SELECT plate FROM owned_vehicles WHERE owner = ? AND plate IN (?) AND job = ?', {xPlayer.identifier, plates, xPlayer.job.name})
if result[1] then
foundPlate, foundNum = result[1].plate, k
break
end
end
if not foundPlate then
cb(false)
else
MySQL.Async.execute('UPDATE owned_vehicles SET `stored` = true WHERE owner = @owner AND plate = @plate AND job = @job', {
['@owner'] = xPlayer.identifier,
['@plate'] = foundPlate,
['@job'] = xPlayer.job.name
}, function (rowsChanged)
if plate then
MySQL.update('UPDATE owned_vehicles SET `stored` = true WHERE owner = ? AND plate = ? AND job = ?', {xPlayer.identifier, plate, xPlayer.job.name},
function(rowsChanged)
if rowsChanged == 0 then
cb(false)
else
cb(true, foundNum)
cb(plate)
end
end)
else
cb(false)
end
end)
function getPriceFromHash(vehicleHash, jobGrade, type)
local vehicles = Config.AuthorizedVehicles[type][jobGrade]
for k,v in ipairs(vehicles) do
if GetHashKey(v.model) == vehicleHash then
return v.price
for i = 1, #vehicles do
local vehicle = vehicles[i]
if GetHashKey(vehicle.model) == vehicleHash then
return vehicle.price
end
end
@@ -277,6 +257,12 @@ end, true, {help = _U('revive_help'), validate = true, arguments = {
{name = 'playerId', help = 'The player id', type = 'player'}
}})
ESX.RegisterCommand('reviveall', "admin", function(xPlayer, args, showError)
for _, playerId in ipairs(GetPlayers()) do
TriggerClientEvent('esx_ambulancejob:revive', playerId)
end
end, false)
ESX.RegisterUsableItem('medikit', function(source)
if not playersHealing[source] then
local xPlayer = ESX.GetPlayerFromId(source)
@@ -305,16 +291,13 @@ end)
ESX.RegisterServerCallback('esx_ambulancejob:getDeathStatus', function(source, cb)
local xPlayer = ESX.GetPlayerFromId(source)
MySQL.scalar('SELECT is_dead FROM users WHERE identifier = ?', {xPlayer.identifier}, function(isDead)
MySQL.Async.fetchScalar('SELECT is_dead FROM users WHERE identifier = @identifier', {
['@identifier'] = xPlayer.identifier
}, function(isDead)
if isDead then
print(('[esx_ambulancejob] [^2INFO^7] "%s" attempted combat logging'):format(xPlayer.identifier))
end
cb(isDead)
if isDead == 1 then
cb(true)
else
cb(false)
end
end)
end)
@@ -323,9 +306,6 @@ AddEventHandler('esx_ambulancejob:setDeathStatus', function(isDead)
local xPlayer = ESX.GetPlayerFromId(source)
if type(isDead) == 'boolean' then
MySQL.Sync.execute('UPDATE users SET is_dead = @isDead WHERE identifier = @identifier', {
['@identifier'] = xPlayer.identifier,
['@isDead'] = isDead
})
MySQL.update('UPDATE users SET is_dead = ? WHERE identifier = ?', {isDead, xPlayer.identifier})
end
end)
+2 -2
View File
@@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
esx_animations
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
esx_animations Copyright (C) 2015-2021 Jérémie N'gadi
esx_animations Copyright (C) 2015-2022 Jérémie N'gadi
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
+1 -1
View File
@@ -28,7 +28,7 @@ start esx_animations
### License
esx_animations - play anims!
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program Is free software: you can redistribute it And/Or modify it under the terms Of the GNU General Public License As published by the Free Software Foundation, either version 3 Of the License, Or (at your option) any later version.
+2 -2
View File
@@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
esx_atm
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
esx_atm Copyright (C) 2015-2021 Jérémie N'gadi
esx_atm Copyright (C) 2015-2022 Jérémie N'gadi
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
+1 -1
View File
@@ -28,7 +28,7 @@ start esx_atm
### License
esx_atm - atm script for ESX
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program Is free software: you can redistribute it And/Or modify it under the terms Of the GNU General Public License As published by the Free Software Foundation, either version 3 Of the License, Or (at your option) any later version.
+1
View File
@@ -52,6 +52,7 @@ Citizen.CreateThread(function()
for k,v in pairs(Config.ATMLocations) do
if #(coords - v) < 1.0 then
isInATMMarker, canSleep = true, false
break
end
+2 -2
View File
@@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
esx_bankerjob
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
esx_bankerjob Copyright (C) 2015-2021 Jérémie N'gadi
esx_bankerjob Copyright (C) 2015-2022 Jérémie N'gadi
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
+1 -1
View File
@@ -35,7 +35,7 @@ start esx_bankerjob
### License
esx_bankerjob - bank script
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program Is free software: you can redistribute it And/Or modify it under the terms Of the GNU General Public License As published by the Free Software Foundation, either version 3 Of the License, Or (at your option) any later version.
+3 -1
View File
@@ -10,7 +10,7 @@ shared_script '@es_extended/imports.lua'
server_scripts {
'@async/async.lua',
'@mysql-async/lib/MySQL.lua',
'@oxmysql/lib/MySQL.lua',
'@es_extended/locale.lua',
'config.lua',
'locales/de.lua',
@@ -20,6 +20,7 @@ server_scripts {
'locales/fi.lua',
'locales/fr.lua',
'locales/sv.lua',
'locales/hu.lua',
'server/main.lua'
}
@@ -33,6 +34,7 @@ client_scripts {
'locales/fi.lua',
'locales/fr.lua',
'locales/sv.lua',
'locales/hu.lua',
'client/main.lua'
}
+18
View File
@@ -0,0 +1,18 @@
Locales['hu'] = {
['actions'] = 'műveletek',
['amount'] = 'összeg',
['balance'] = 'egyenleg',
['bank'] = 'bank',
['bill_amount'] = 'Számla összege',
['billing'] = 'Számlázás',
['customer'] = 'Vevő',
['customers'] = 'Kliensek',
['deposit'] = 'Befizetés',
['invalid_amount'] = 'Érvénytelen mennyiség',
['no_player_nearby'] = 'Nincsen játékos a közeledben',
['press_input_context_to_open_menu'] = 'Nyomj ~INPUT_CONTEXT~ hogy megnyisd a bankot.',
['withdraw'] = 'Kivétel',
['boss_actions'] = 'Főnöki menü',
['phone_receive'] = 'banki ügyfél',
['phone_label'] = 'bank',
}
+2 -2
View File
@@ -56,7 +56,7 @@ end)
function CalculateBankSavings(d, h, m)
local asyncTasks = {}
MySQL.Async.fetchAll('SELECT * FROM addon_account_data WHERE account_name = @account_name', {
MySQL.query('SELECT * FROM addon_account_data WHERE account_name = @account_name', {
['@account_name'] = 'bank_savings'
}, function(result)
local bankInterests = 0
@@ -80,7 +80,7 @@ function CalculateBankSavings(d, h, m)
local scope = function(newMoney, owner)
table.insert(asyncTasks, function(cb)
MySQL.Async.execute('UPDATE addon_account_data SET money = @money WHERE owner = @owner AND account_name = @account_name', {
MySQL.update('UPDATE addon_account_data SET money = @money WHERE owner = @owner AND account_name = @account_name', {
['@money'] = newMoney,
['@owner'] = owner,
['@account_name'] = 'bank_savings',
+2 -2
View File
@@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
esx_barbershop
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
esx_barbershop Copyright (C) 2015-2021 Jérémie N'gadi
esx_barbershop Copyright (C) 2015-2022 Jérémie N'gadi
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
+1 -1
View File
@@ -31,7 +31,7 @@ start esx_barbershop
### License
esx_barbershop - barber shop!
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program Is free software: you can redistribute it And/Or modify it under the terms Of the GNU General Public License As published by the Free Software Foundation, either version 3 Of the License, Or (at your option) any later version.
@@ -19,6 +19,7 @@ server_scripts {
'locales/cs.lua',
'locales/pl.lua',
'locales/tr.lua',
'locales/hu.lua',
'config.lua',
'server/main.lua'
}
@@ -34,6 +35,7 @@ client_scripts {
'locales/cs.lua',
'locales/pl.lua',
'locales/tr.lua',
'locales/hu.lua',
'config.lua',
'client/main.lua'
}
@@ -0,0 +1,9 @@
Locales['hu'] = {
['valid_purchase'] = 'Biztosan kifizeted?',
['yes'] = 'Igen',
['no'] = 'Nem',
['not_enough_money'] = 'Nincsen elég pénzed',
['press_access'] = 'Nyomj ~INPUT_CONTEXT~ hogy megnyisd a ~y~Fodrászatot~s~.',
['barber_blip'] = 'Fodrászat',
['you_paid'] = 'Fizettél ~g~$%s~s~',
}
+2 -2
View File
@@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
esx_basicneeds
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
esx_basicneeds Copyright (C) 2015-2021 Jérémie N'gadi
esx_basicneeds Copyright (C) 2015-2022 Jérémie N'gadi
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
+1 -1
View File
@@ -34,7 +34,7 @@ start esx_basicneeds
### License
esx_basicneeds - thirst and hunger system
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program Is free software: you can redistribute it And/Or modify it under the terms Of the GNU General Public License As published by the Free Software Foundation, either version 3 Of the License, Or (at your option) any later version.
@@ -19,6 +19,7 @@ server_scripts {
'locales/sv.lua',
'locales/pl.lua',
'locales/tr.lua',
'locales/hu.lua',
'config.lua',
'server/main.lua'
}
@@ -34,6 +35,7 @@ client_scripts {
'locales/sv.lua',
'locales/pl.lua',
'locales/tr.lua',
'locales/hu.lua',
'config.lua',
'client/main.lua'
}
@@ -0,0 +1,4 @@
Locales['hu'] = {
['used_bread'] = 'Megettél egy ~y~1x~s~ ~b~kenyeret~s~.',
['used_water'] = 'Megittál egy ~y~1x~s~ ~b~vizet~s~.',
}
+2 -2
View File
@@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
esx_billing
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
esx_billing Copyright (C) 2015-2021 Jérémie N'gadi
esx_billing Copyright (C) 2015-2022 Jérémie N'gadi
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
+1 -1
View File
@@ -48,7 +48,7 @@ end
### License
esx_billing - billing for ESX
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program Is free software: you can redistribute it And/Or modify it under the terms Of the GNU General Public License As published by the Free Software Foundation, either version 3 Of the License, Or (at your option) any later version.
+3 -1
View File
@@ -9,7 +9,7 @@ version 'legacy'
shared_script '@es_extended/imports.lua'
server_scripts {
'@mysql-async/lib/MySQL.lua',
'@oxmysql/lib/MySQL.lua',
'@es_extended/locale.lua',
'locales/de.lua',
'locales/br.lua',
@@ -21,6 +21,7 @@ server_scripts {
'locales/pl.lua',
'locales/cs.lua',
'locales/tr.lua',
'locales/hu.lua',
'config.lua',
'server/main.lua'
}
@@ -37,6 +38,7 @@ client_scripts {
'locales/pl.lua',
'locales/cs.lua',
'locales/tr.lua',
'locales/hu.lua',
'config.lua',
'client/main.lua'
}
+10 -10
View File
@@ -1,12 +1,12 @@
Locales['de'] = {
['invoices'] = 'rechnungen',
['invoices'] = 'Rechnungen',
['invoices_item'] = '$%s',
['received_invoice'] = 'you hast eine Rechnung ~r~erhlaten~s~',
['paid_invoice'] = 'du ~g~bezahlst~s~ eine Rechnung von ~r~$%s~s~',
['no_invoices'] = 'you do not have any bills to pay at this moment',
['received_payment'] = 'du ~g~erhältst~s~ eine Zahlung von ~r~$%s~s~',
['player_not_online'] = 'der Spieler ist nicht online',
['no_money'] = 'you do not have enough money to pay this bill',
['target_no_money'] = 'the player ~r~does not~s~ have enough money to pay the bill!',
['keymap_showbills'] = 'open bills menu',
}
['received_invoice'] = 'Sie haben eine Rechnung ~r~erhalten~s~.',
['paid_invoice'] = 'Sie ~g~bezahlen~s~ eine Rechnung von ~r~$%s~s~.',
['no_invoices'] = 'Sie haben keine offenen Rechnungen.',
['received_payment'] = 'Sie ~g~erhalten~s~ eine Zahlung von ~r~$%s~s~.',
['player_not_online'] = 'Die Person ist nicht erreichbar.',
['no_money'] = 'Sie haben nicht genug Geld, um diese Rechnung zu bezahlen.',
['target_no_money'] = 'Die Person kann die Rechnung nicht bezahlen.',
['keymap_showbills'] = 'Rechnungen anzeigen',
}
+12
View File
@@ -0,0 +1,12 @@
Locales['hu'] = {
['invoices'] = 'Számlák',
['invoices_item'] = '$%s',
['received_invoice'] = 'Kaptál egy számlát',
['paid_invoice'] = 'Befizettél egy számlát ( ~r~$%s~s~ )',
['no_invoices'] = 'Nincsen számlád amit kifizethetnél',
['received_payment'] = 'Fizetést kaptál: ~r~$%s~s~',
['player_not_online'] = 'A játékos nem elérhető',
['no_money'] = 'Nincsen elég pénzed, hogy kifizesd ezt a számlát',
['target_no_money'] = 'A játékosnak nincsen annyi pénze, hogy befizesse a számlát',
['keymap_showbills'] = 'Számlák megnézése',
}
+22 -41
View File
@@ -7,25 +7,13 @@ AddEventHandler('esx_billing:sendBill', function(playerId, sharedAccountName, la
if amount > 0 and xTarget then
TriggerEvent('esx_addonaccount:getSharedAccount', sharedAccountName, function(account)
if account then
MySQL.Async.execute('INSERT INTO billing (identifier, sender, target_type, target, label, amount) VALUES (@identifier, @sender, @target_type, @target, @label, @amount)', {
['@identifier'] = xTarget.identifier,
['@sender'] = xPlayer.identifier,
['@target_type'] = 'society',
['@target'] = sharedAccountName,
['@label'] = label,
['@amount'] = amount
}, function(rowsChanged)
MySQL.insert('INSERT INTO billing (identifier, sender, target_type, target, label, amount) VALUES (?, ?, ?, ?, ?, ?)', {xTarget.identifier, xPlayer.identifier, 'society', sharedAccountName, label, amount},
function(rowsChanged)
xTarget.showNotification(_U('received_invoice'))
end)
else
MySQL.Async.execute('INSERT INTO billing (identifier, sender, target_type, target, label, amount) VALUES (@identifier, @sender, @target_type, @target, @label, @amount)', {
['@identifier'] = xTarget.identifier,
['@sender'] = xPlayer.identifier,
['@target_type'] = 'player',
['@target'] = xPlayer.identifier,
['@label'] = label,
['@amount'] = amount
}, function(rowsChanged)
MySQL.insert('INSERT INTO billing (identifier, sender, target_type, target, label, amount) VALUES (?, ?, ?, ?, ?, ?)', {xTarget.identifier, xPlayer.identifier, 'player', xPlayer.identifier, label, amount},
function(rowsChanged)
xTarget.showNotification(_U('received_invoice'))
end)
end
@@ -36,9 +24,8 @@ end)
ESX.RegisterServerCallback('esx_billing:getBills', function(source, cb)
local xPlayer = ESX.GetPlayerFromId(source)
MySQL.Async.fetchAll('SELECT amount, id, label FROM billing WHERE identifier = @identifier', {
['@identifier'] = xPlayer.identifier
}, function(result)
MySQL.query('SELECT amount, id, label FROM billing WHERE identifier = ?', {xPlayer.identifier},
function(result)
cb(result)
end)
end)
@@ -47,9 +34,8 @@ ESX.RegisterServerCallback('esx_billing:getTargetBills', function(source, cb, ta
local xPlayer = ESX.GetPlayerFromId(target)
if xPlayer then
MySQL.Async.fetchAll('SELECT amount, id, label FROM billing WHERE identifier = @identifier', {
['@identifier'] = xPlayer.identifier
}, function(result)
MySQL.query('SELECT amount, id, label FROM billing WHERE identifier = ?', {xPlayer.identifier},
function(result)
cb(result)
end)
else
@@ -60,19 +46,17 @@ end)
ESX.RegisterServerCallback('esx_billing:payBill', function(source, cb, billId)
local xPlayer = ESX.GetPlayerFromId(source)
MySQL.Async.fetchAll('SELECT sender, target_type, target, amount FROM billing WHERE id = @id', {
['@id'] = billId
}, function(result)
if result[1] then
local amount = result[1].amount
local xTarget = ESX.GetPlayerFromIdentifier(result[1].sender)
MySQL.single('SELECT sender, target_type, target, amount FROM billing WHERE id = ?', {billId},
function(result)
if result then
local amount = result.amount
local xTarget = ESX.GetPlayerFromIdentifier(result.sender)
if result[1].target_type == 'player' then
if result.target_type == 'player' then
if xTarget then
if xPlayer.getMoney() >= amount then
MySQL.Async.execute('DELETE FROM billing WHERE id = @id', {
['@id'] = billId
}, function(rowsChanged)
MySQL.update('DELETE FROM billing WHERE id = ?', {billId},
function(rowsChanged)
if rowsChanged == 1 then
xPlayer.removeMoney(amount)
xTarget.addMoney(amount)
@@ -84,9 +68,8 @@ ESX.RegisterServerCallback('esx_billing:payBill', function(source, cb, billId)
cb()
end)
elseif xPlayer.getAccount('bank').money >= amount then
MySQL.Async.execute('DELETE FROM billing WHERE id = @id', {
['@id'] = billId
}, function(rowsChanged)
MySQL.update('DELETE FROM billing WHERE id = ?', {billId},
function(rowsChanged)
if rowsChanged == 1 then
xPlayer.removeAccountMoney('bank', amount)
xTarget.addAccountMoney('bank', amount)
@@ -109,9 +92,8 @@ ESX.RegisterServerCallback('esx_billing:payBill', function(source, cb, billId)
else
TriggerEvent('esx_addonaccount:getSharedAccount', result[1].target, function(account)
if xPlayer.getMoney() >= amount then
MySQL.Async.execute('DELETE FROM billing WHERE id = @id', {
['@id'] = billId
}, function(rowsChanged)
MySQL.update('DELETE FROM billing WHERE id = ?', {billId},
function(rowsChanged)
if rowsChanged == 1 then
xPlayer.removeMoney(amount)
account.addMoney(amount)
@@ -125,9 +107,8 @@ ESX.RegisterServerCallback('esx_billing:payBill', function(source, cb, billId)
cb()
end)
elseif xPlayer.getAccount('bank').money >= amount then
MySQL.Async.execute('DELETE FROM billing WHERE id = @id', {
['@id'] = billId
}, function(rowsChanged)
MySQL.update('DELETE FROM billing WHERE id = ?', {billId},
function(rowsChanged)
if rowsChanged == 1 then
xPlayer.removeAccountMoney('bank', amount)
account.addMoney(amount)
+2 -2
View File
@@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
esx_boat
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
esx_boat Copyright (C) 2015-2021 Jérémie N'gadi
esx_boat Copyright (C) 2015-2022 Jérémie N'gadi
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
+1 -1
View File
@@ -33,7 +33,7 @@ start esx_boat
### License
esx_boat - Boat shop and garage for ESX
Copyright (C) 2015-2021 Jérémie N'gadi
Copyright (C) 2015-2022 Jérémie N'gadi
This program Is free software: you can redistribute it And/Or modify it under the terms Of the GNU General Public License As published by the Free Software Foundation, either version 3 Of the License, Or (at your option) any later version.
+3 -1
View File
@@ -9,13 +9,14 @@ version 'legacy'
shared_script '@es_extended/imports.lua'
server_scripts {
'@mysql-async/lib/MySQL.lua',
'@oxmysql/lib/MySQL.lua',
'@es_extended/locale.lua',
'locales/en.lua',
'locales/fr.lua',
'locales/sv.lua',
'locales/pl.lua',
'locales/es.lua',
'locales/hu.lua',
'config.lua',
'server/main.lua'
}
@@ -27,6 +28,7 @@ client_scripts {
'locales/sv.lua',
'locales/pl.lua',
'locales/es.lua',
'locales/hu.lua',
'config.lua',
'client/main.lua',
'client/marker.lua'
+31
View File
@@ -0,0 +1,31 @@
Locales['hu'] = {
-- shop
['boat_shop'] = 'Hajóbolt',
['boat_shop_open'] = 'Nyomj ~INPUT_CONTEXT~ hogy megnézd a hajókat',
['boat_shop_confirm'] = 'hajó: <span style="color: yellow;">%s</span> ára: <span style="color: orange;">$%s</span>',
['boat_shop_bought'] = 'Vettél ~b~%s~s~ ennyiért: ~g~$%s~s~',
['boat_shop_nomoney'] = '~r~Ezt nem engedheted meg magadnak!',
['confirm_no'] = 'Nem',
['confirm_yes'] = 'Igen',
-- garage
['garage'] = 'Hajógarázs',
['garage_open'] = 'Nyomj ~INPUT_CONTEXT~ hogy megnyisd a garázst',
['garage_store'] = 'Nyomj ~INPUT_CONTEXT~ hogy kikösd a hajót',
['garage_taken'] = 'Sikeresen kivetted a hajót',
['garage_stored'] = 'Sikeresen leraktad a hajót',
['garage_noboats'] = '~r~Nincsen hajód',
['garage_blocked'] = '~r~A lehívási pont blokkolva',
['garage_notowner'] = '~r~Nem a tied ez a hajó',
-- license
['license_menu'] = 'Szeretnél venni hajó engedélyt?',
['license_buy_no'] = 'Nem',
['license_buy_yes'] = 'Vegyél hajó engedélyt <span style="color: green;">$%s</span>-ért',
['license_bought'] = 'Vettél ~y~hajó engedélyt~s~ ~g~$%s~s~-ért',
['license_nomoney'] = '~r~nem engedheted meg~s~ magadnak, hogy vegyél ~y~hajó engedélyt~s~!',
-- blips
['blip_garage'] = 'Hajógarázs',
['blip_shop'] = 'Hajóbolt',
}

Some files were not shown because too many files have changed in this diff Show More