Merge branch 'dev' into OneSyncSpawn

This commit is contained in:
Kenshin13
2025-06-15 18:59:30 +02:00
committed by GitHub
163 changed files with 2998 additions and 1851 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ name: Bug report
about: Create a report to help us improve
title: "[Bug] - esx_script - Issue"
labels: bug
assignees: Arctos2win, Kenshiin13
assignees: Kenshiin13
---
+1 -1
View File
@@ -3,7 +3,7 @@ name: Feature Request
about: Help us improve esx with your ideas
title: "[Feature Request] - esx_script - Add better configuration"
labels: enhancement
assignees: Arctos2win, Kenshiin13
assignees: Kenshiin13
---
-22
View File
@@ -1,22 +0,0 @@
### Description
<!-- Explain What this PR does -->
---
### Motivation
<!-- Explain why you are making this PR -->
---
### **Implementation Details**
<!-- Explain how your implemenation meets your goal -->
---
### Usage Example
<!-- If you are adding or editing functions/events show usage examples -->
---
### PR Checklist
- [] My commit messages and PR title follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) standard.
- [] My changes have been tested locally and function as expected.
- [] My PR does not introduce any breaking changes.
- [] I have provided a clear explanation of what my PR does, including the reasoning behind the changes and any relevant context.
+1 -1
View File
@@ -4,6 +4,6 @@ game 'gta5'
author 'ESX-Framework'
description 'Allows resources to Run tasks at specific intervals.'
lua54 'yes'
version '1.12.4'
version '1.12.2'
server_script 'server/main.lua'
+21 -22
View File
@@ -152,9 +152,10 @@ end
---@param message string The message to show
---@param notifyType? string The type of notification to show
---@param length? number The length of the notification
---@param title? string The title of the notification
---@return nil
function ESX.ShowNotification(message, notifyType, length)
return IsResourceFound('esx_notify') and exports['esx_notify']:Notify(notifyType, length, message)
function ESX.ShowNotification(message, notifyType, length, title)
return IsResourceFound('esx_notify') and exports['esx_notify']:Notify(notifyType, length, message, title)
end
function ESX.TextUI(...)
@@ -805,14 +806,18 @@ function ESX.Game.GetVehicleProperties(vehicle)
return
end
---@type number | number[], number | number[]
local colorPrimary, colorSecondary = GetVehicleColours(vehicle)
local pearlescentColor, wheelColor = GetVehicleExtraColours(vehicle)
local hasCustomPrimaryColor = GetIsVehiclePrimaryColourCustom(vehicle)
local dashboardColor = GetVehicleDashboardColor(vehicle)
local interiorColor = GetVehicleInteriorColour(vehicle)
local customPrimaryColor = nil
if hasCustomPrimaryColor then
customPrimaryColor = { GetVehicleCustomPrimaryColour(vehicle) }
if GetIsVehiclePrimaryColourCustom(vehicle) then
colorPrimary = { GetVehicleCustomPrimaryColour(vehicle) }
end
if GetIsVehicleSecondaryColourCustom(vehicle) then
colorSecondary = { GetVehicleCustomSecondaryColour(vehicle) }
end
local hasCustomXenonColor, customXenonColorR, customXenonColorG, customXenonColorB = GetVehicleXenonLightsCustomColor(vehicle)
@@ -821,12 +826,6 @@ function ESX.Game.GetVehicleProperties(vehicle)
customXenonColor = { customXenonColorR, customXenonColorG, customXenonColorB }
end
local hasCustomSecondaryColor = GetIsVehicleSecondaryColourCustom(vehicle)
local customSecondaryColor = nil
if hasCustomSecondaryColor then
customSecondaryColor = { GetVehicleCustomSecondaryColour(vehicle) }
end
local extras = {}
for extraId = 0, 20 do
if DoesExtraExist(vehicle, extraId) then
@@ -879,8 +878,6 @@ function ESX.Game.GetVehicleProperties(vehicle)
dirtLevel = ESX.Math.Round(GetVehicleDirtLevel(vehicle), 1),
color1 = colorPrimary,
color2 = colorSecondary,
customPrimaryColor = customPrimaryColor,
customSecondaryColor = customSecondaryColor,
pearlescentColor = pearlescentColor,
wheelColor = wheelColor,
@@ -991,17 +988,19 @@ function ESX.Game.SetVehicleProperties(vehicle, props)
if props.dirtLevel ~= nil then
SetVehicleDirtLevel(vehicle, props.dirtLevel + 0.0)
end
if props.customPrimaryColor ~= nil then
SetVehicleCustomPrimaryColour(vehicle, props.customPrimaryColor[1], props.customPrimaryColor[2], props.customPrimaryColor[3])
end
if props.customSecondaryColor ~= nil then
SetVehicleCustomSecondaryColour(vehicle, props.customSecondaryColor[1], props.customSecondaryColor[2], props.customSecondaryColor[3])
end
if props.color1 ~= nil then
SetVehicleColours(vehicle, props.color1, colorSecondary)
if type(props.color1) == "table" then
SetVehicleCustomPrimaryColour(vehicle, props.color1[1], props.color1[2], props.color1[3])
else
SetVehicleColours(vehicle, props.color1, colorSecondary)
end
end
if props.color2 ~= nil then
SetVehicleColours(vehicle, props.color1 or colorPrimary, props.color2)
if type(props.color2) == "table" then
SetVehicleCustomSecondaryColour(vehicle, props.color2[1], props.color2[2], props.color2[3])
else
SetVehicleColours(vehicle, props.color1 or colorPrimary, props.color2)
end
end
if props.pearlescentColor ~= nil then
SetVehicleExtraColours(vehicle, props.pearlescentColor, wheelColor)
@@ -4,7 +4,7 @@ function Adjustments:RemoveHudComponents()
for i = 1, #Config.RemoveHudComponents do
if Config.RemoveHudComponents[i] then
SetHudComponentSize(i, 0.0, 0.0)
SetHudComponentPosition(i, 900, 900)
SetHudComponentPosition(i, 900.0, 900.0)
end
end
end
+23 -24
View File
@@ -14,8 +14,25 @@ Callbacks.id = 0
-- MARK: Internal Functions
-- =============================================
function Callbacks:Trigger(event, cb, invoker, ...)
function Callbacks:Register(name, resource, cb)
self.storage[name] = {
resource = resource,
cb = cb
}
end
function Callbacks:Execute(cb, id, ...)
local success, errorString = pcall(cb, ...)
if not success then
print(("[^1ERROR^7] Failed to execute Callback with RequestId: ^5%s^7"):format(id))
error(errorString)
return
end
end
function Callbacks:Trigger(event, cb, invoker, ...)
self.requests[self.id] = {
await = type(cb) == "boolean",
cb = cb or promise:new()
@@ -29,16 +46,6 @@ function Callbacks:Trigger(event, cb, invoker, ...)
return table.cb
end
function Callbacks:Execute(cb, id, ...)
local success, errorString = pcall(cb, ...)
if not success then
print(("[^1ERROR^7] Failed to execute Callback with RequestId: ^5%s^7"):format(id))
error(errorString)
return
end
end
function Callbacks:ServerRecieve(requestId, invoker, ...)
if not self.requests[requestId] then
return error(("Server Callback with requestId ^5%s^1 Was Called by ^5%s^1 but does not exist."):format(requestId, invoker))
@@ -49,21 +56,13 @@ function Callbacks:ServerRecieve(requestId, invoker, ...)
self.requests[requestId] = nil
if callback.await then
callback.cb:resolve({...})
callback.cb:resolve({ ... })
else
self:Execute(callback.cb, requestId, ...)
end
end
function Callbacks:Register(name, resource, cb)
self.storage[name] = {
resource = resource,
cb = cb
}
end
function Callbacks:ClientRecieve(eventName, requestId, invoker, ...)
if not self.storage[eventName] then
return error(("Client Callback with requestId ^5%s^1 Was Called by ^5%s^1 but does not exist."):format(eventName, invoker))
end
@@ -130,14 +129,14 @@ end
-- MARK: Events
-- =============================================
ESX.SecureNetEvent("esx:triggerClientCallback", function(...)
Callbacks:ClientRecieve(...)
end)
ESX.SecureNetEvent("esx:serverCallback", function(...)
Callbacks:ServerRecieve(...)
end)
ESX.SecureNetEvent("esx:triggerClientCallback", function(...)
Callbacks:ClientRecieve(...)
end)
AddEventHandler("onResourceStop", function(resource)
for k, v in pairs(Callbacks.storage) do
if v.resource == resource then
+52 -54
View File
@@ -2,17 +2,11 @@ ESX.Scaleform = {}
ESX.Scaleform.Utils = {}
function ESX.Scaleform.ShowFreemodeMessage(title, msg, sec)
local scaleform = ESX.Scaleform.Utils.RequestScaleformMovie("MP_BIG_MESSAGE_FREEMODE")
BeginScaleformMovieMethod(scaleform, "SHOW_SHARD_WASTED_MP_MESSAGE")
ScaleformMovieMethodAddParamTextureNameString(title)
ScaleformMovieMethodAddParamTextureNameString(msg)
EndScaleformMovieMethod()
while sec > 0 do
local scaleform = ESX.Scaleform.Utils.RunMethod("MP_BIG_MESSAGE_FREEMODE", "SHOW_SHARD_WASTED_MP_MESSAGE", false, title, msg)
local endTime = GetGameTimer() + (sec * 1000)
while GetGameTimer() < endTime do
Wait(0)
sec = sec - 0.01
DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 255, 0)
end
@@ -20,30 +14,13 @@ function ESX.Scaleform.ShowFreemodeMessage(title, msg, sec)
end
function ESX.Scaleform.ShowBreakingNews(title, msg, bottom, sec)
local scaleform = ESX.Scaleform.Utils.RequestScaleformMovie("BREAKING_NEWS")
local scaleform = ESX.Scaleform.Utils.RunMethod("BREAKING_NEWS", "SET_TEXT", false, msg, bottom)
ESX.Scaleform.Utils.RunMethod(scaleform, "SET_SCROLL_TEXT", false, 0, 0, title)
ESX.Scaleform.Utils.RunMethod(scaleform, "DISPLAY_SCROLL_TEXT", false, 0, 0)
BeginScaleformMovieMethod(scaleform, "SET_TEXT")
ScaleformMovieMethodAddParamTextureNameString(msg)
ScaleformMovieMethodAddParamTextureNameString(bottom)
EndScaleformMovieMethod()
BeginScaleformMovieMethod(scaleform, "SET_SCROLL_TEXT")
ScaleformMovieMethodAddParamInt(0) -- top ticker
ScaleformMovieMethodAddParamInt(0) -- Since this is the first string, start at 0
ScaleformMovieMethodAddParamTextureNameString(title)
EndScaleformMovieMethod()
BeginScaleformMovieMethod(scaleform, "DISPLAY_SCROLL_TEXT")
ScaleformMovieMethodAddParamInt(0) -- Top ticker
ScaleformMovieMethodAddParamInt(0) -- Index of string
EndScaleformMovieMethod()
while sec > 0 do
local endTime = GetGameTimer() + (sec * 1000)
while GetGameTimer() < endTime do
Wait(0)
sec = sec - 0.01
DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 255, 0)
end
@@ -51,22 +28,11 @@ function ESX.Scaleform.ShowBreakingNews(title, msg, bottom, sec)
end
function ESX.Scaleform.ShowPopupWarning(title, msg, bottom, sec)
local scaleform = ESX.Scaleform.Utils.RequestScaleformMovie("POPUP_WARNING")
local scaleform = ESX.Scaleform.Utils.RunMethod("POPUP_WARNING", "SHOW_POPUP_WARNING", false, 500.0, title, msg, bottom, true)
BeginScaleformMovieMethod(scaleform, "SHOW_POPUP_WARNING")
ScaleformMovieMethodAddParamFloat(500.0) -- black background
ScaleformMovieMethodAddParamTextureNameString(title)
ScaleformMovieMethodAddParamTextureNameString(msg)
ScaleformMovieMethodAddParamTextureNameString(bottom)
ScaleformMovieMethodAddParamBool(true)
EndScaleformMovieMethod()
while sec > 0 do
local endTime = GetGameTimer() + (sec * 1000)
while GetGameTimer() < endTime do
Wait(0)
sec = sec - 0.01
DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 255, 0)
end
@@ -74,16 +40,11 @@ function ESX.Scaleform.ShowPopupWarning(title, msg, bottom, sec)
end
function ESX.Scaleform.ShowTrafficMovie(sec)
local scaleform = ESX.Scaleform.Utils.RequestScaleformMovie("TRAFFIC_CAM")
local scaleform = ESX.Scaleform.Utils.RunMethod("TRAFFIC_CAM", "PLAY_CAM_MOVIE", false)
BeginScaleformMovieMethod(scaleform, "PLAY_CAM_MOVIE")
EndScaleformMovieMethod()
while sec > 0 do
local endTime = GetGameTimer() + (sec * 1000)
while GetGameTimer() < endTime do
Wait(0)
sec = sec - 0.01
DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 255, 0)
end
@@ -99,3 +60,40 @@ function ESX.Scaleform.Utils.RequestScaleformMovie(movie)
return scaleform
end
--- Executes a method on a scaleform movie with optional arguments and return value.
--- The caller is responsible for disposing of the scaleform using `SetScaleformMovieAsNoLongerNeeded`.
---@param scaleform number|string # Scaleform handle or name to request the scaleform movie
---@param methodName string # The method name to call on the scaleform
---@param returnValue? boolean # Whether to return the value from the method
---@param ... number|string|boolean # Arguments to pass to the method
---@return number, number? # The scaleform handle, and the return value if `returnValue` is true
function ESX.Scaleform.Utils.RunMethod(scaleform, methodName, returnValue, ...)
scaleform = type(scaleform) == "number" and scaleform or ESX.Scaleform.Utils.RequestScaleformMovie(scaleform)
BeginScaleformMovieMethod(scaleform, methodName)
local args = { ... }
for i, arg in ipairs(args) do
local typeArg = type(arg)
if typeArg == "number" then
if math.type(arg) == "float" then
ScaleformMovieMethodAddParamFloat(arg)
else
ScaleformMovieMethodAddParamInt(arg)
end
elseif typeArg == "string" then
ScaleformMovieMethodAddParamTextureNameString(arg)
elseif typeArg == "boolean" then
ScaleformMovieMethodAddParamBool(arg)
end
end
if returnValue then
return scaleform, EndScaleformMovieMethodReturnValue()
end
EndScaleformMovieMethod()
return scaleform
end
+3 -2
View File
@@ -3,11 +3,10 @@ fx_version 'cerulean'
game 'gta5'
description 'The Core resource that provides the functionalities for all other resources.'
lua54 'yes'
version '1.12.4'
version '1.12.2'
shared_scripts {
'locale.lua',
'locales/*.lua',
'shared/config/main.lua',
'shared/config/weapons.lua',
@@ -25,6 +24,7 @@ server_scripts {
'server/common.lua',
'server/modules/callback.lua',
'server/classes/player.lua',
'server/classes/vehicle.lua',
'server/classes/overrides/*.lua',
'server/functions.lua',
'server/modules/onesync.lua',
@@ -62,6 +62,7 @@ ui_page {
files {
'imports.lua',
'locales/*.lua',
'locale.js',
'html/ui.html',
+21
View File
@@ -42,6 +42,27 @@ if not IsDuplicityVersion() then -- Only register this event for the client
return error(('\n^1Error loading module (%s)'):format(external[i]))
end
end
else
ESX.Player = setmetatable({}, {
__call = function(_, src)
if type(src) ~= "number" then
src = ESX.GetPlayerIdFromIdentifier(src)
if not src then
return
end
elseif not ESX.IsPlayerLoaded(src) then
return
end
return setmetatable({src = src}, {
__index = function(self, method)
return function(...)
return exports.es_extended:RunStaticPlayerMethod(self.src, method, ...)
end
end
})
end
})
end
if GetResourceState("ox_lib") == "missing" then
+25 -13
View File
@@ -3,21 +3,33 @@ Locales = {}
function Translate(str, ...) -- Translate string
if not str then
error(("Resource ^5%s^1 You did not specify a parameter for the Translate function or the value is nil!"):format(GetInvokingResource() or GetCurrentResourceName()))
return "Given translate function parameter is nil!"
end
if Locales[Config.Locale] then
if Locales[Config.Locale][str] then
return string.format(Locales[Config.Locale][str], ...)
elseif Config.Locale ~= "en" and Locales["en"] and Locales["en"][str] then
return string.format(Locales["en"][str], ...)
else
return "Translation [" .. Config.Locale .. "][" .. str .. "] does not exist"
--- Load the locale file if it hasn't been loaded yet
if Locales[Config.Locale] == nil then
local success, result = pcall(function()
return assert(load(LoadResourceFile(GetCurrentResourceName(), ("locales/%s.lua"):format(Config.Locale))))()
end)
Locales[Config.Locale] = success and result or false
end
local translations = Locales[Config.Locale]
if not translations then
if Config.Locale == "en" then
return "Locale [en] does not exist"
end
elseif Config.Locale ~= "en" and Locales["en"] and Locales["en"][str] then
return string.format(Locales["en"][str], ...)
else
return "Locale [" .. Config.Locale .. "] does not exist"
-- Fall back to English translation if the current locale is not found
Config.Locale = "en"
return Translate(str, ...)
end
if translations[str] then
return translations[str]:format(...)
end
return ("Translation [%s][%s] does not exist"):format(Config.Locale, str)
end
function TranslateCap(str, ...) -- Translate string first char uppercase
@@ -26,4 +38,4 @@ end
_ = Translate
-- luacheck: ignore _U
_U = TranslateCap
_U = TranslateCap
+4 -4
View File
@@ -1,4 +1,4 @@
Locales["cs"] = {
return {
-- Inventory
["inventory"] = "Inventář ( Váha %s / %s )",
["use"] = "Použít",
@@ -223,10 +223,10 @@ Locales["cs"] = {
["weapon_tactilerifle"] = "Service Carbine",
-- Drug Wars DLC
["weapon_candycane"] = "Candy Cane", -- not translated
["weapon_candycane"] = "Candy Cane", -- not translated
["weapon_acidpackage"] = "Acid Package", -- not translated
["weapon_pistolxm3"] = "WM 29 Pistol", -- not translated
["weapon_railgunxm3"] = "Railgun", -- not translated
["weapon_pistolxm3"] = "WM 29 Pistol", -- not translated
["weapon_railgunxm3"] = "Railgun", -- not translated
-- Thrown
["weapon_ball"] = "Míček",
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["de"] = {
return {
-- Inventory
["inventory"] = "Inventar ( Gewicht %s / %s )",
["use"] = "Benutzen",
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["el"] = {
return {
-- Inventory
["inventory"] = "Αποθήκη ( Βάρος %s / %s )",
["use"] = "Χρήση",
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["en"] = {
return {
-- Inventory
["inventory"] = "Inventory ( Weight %s / %s )",
["use"] = "Use",
+325 -299
View File
@@ -1,399 +1,425 @@
Locales["es"] = {
return {
-- Inventory
["inventory"] = "Inventario %s / %s",
["inventory"] = "Inventario (Peso %s / %s)",
["use"] = "Usar",
["give"] = "Dar",
["remove"] = "Tirar",
["return"] = "Volver",
["return"] = "Devolver",
["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 %sx %s a %s",
["received_item"] = "Has recibido %sx %s de %s",
["gave_weapon"] = "Has dado %s a %s",
["gave_weapon_ammo"] = "Has dado ~o~%sx %s para %s a %s",
["gave_weapon_withammo"] = "Has dado %s con ~o~%sx %s a %s",
["gave_weapon_hasalready"] = "%s ya tiene un/a %s",
["gave_weapon_noweapon"] = "%s no tiene ese arma",
["received_weapon"] = "Has recibido %s de %s",
["received_weapon_ammo"] = "Has recibido ~o~%sx %s para su %s de %s",
["received_weapon_withammo"] = "Has recibido %s con ~o~%sx %s de %s",
["received_weapon_hasalready"] = "%s intentó darle un/a %s, pero ya tienes uno",
["received_weapon_noweapon"] = "%s intentó darles munición para un %s, pero no tiene uno",
["gave_account_money"] = "Has dado $%s (%s) a %s",
["received_account_money"] = "Has recibido $%s (%s) de %s",
["noammo"] = "¡Insuficiente!",
["gave_item"] = "Dando %sx %s a %s",
["received_item"] = "Recibido %sx %s de %s",
["gave_weapon"] = "Dando %s a %s",
["gave_weapon_ammo"] = "Dando ~o~%sx %s para %s a %s",
["gave_weapon_withammo"] = "Dando %s con ~o~%sx %s a %s",
["gave_weapon_hasalready"] = "%s ya tiene un %s",
["gave_weapon_noweapon"] = "%s no tiene esa arma",
["received_weapon"] = "Recibido %s de %s",
["received_weapon_ammo"] = "Recibido ~o~%sx %s para tu %s de %s",
["received_weapon_withammo"] = "Recibido %s con ~o~%sx %s de %s",
["received_weapon_hasalready"] = "%s ha intentado darte un %s, pero ya tienes esta arma",
["received_weapon_noweapon"] = "%s ha intentado darte munición para un %s, pero no tienes esta arma",
["gave_account_money"] = "Dando $%s (%s) a %s",
["received_account_money"] = "Recibido $%s (%s) de %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 %s",
["imp_invalid_quantity"] = "Acción imposible, cantidad inválida",
["imp_invalid_amount"] = "Acción imposible, cantidad inválida",
["threw_standard"] = "Has tirado %sx %s",
["threw_account"] = "Has tirado $%s %s",
["threw_weapon"] = "Has tirado %s",
["threw_weapon_ammo"] = "Has tirado %s con ~o~%sx %s",
["threw_weapon_already"] = "Ya llevas el mismo arma",
["threw_cannot_pickup"] = "No puedes recogerlo porque tu inventario está lleno!",
["ex_inv_lim"] = "No se puede realizar la acción, se excede el peso máximo de %s",
["imp_invalid_quantity"] = "No se puede realizar la acción, la cantidad es inválida",
["imp_invalid_amount"] = "No se puede realizar la acción, la cantidad es inválida",
["threw_standard"] = "Tirando %sx %s",
["threw_account"] = "Tirando $%s %s",
["threw_weapon"] = "Tirando %s",
["threw_weapon_ammo"] = "Tirando %s con ~o~%sx %s",
["threw_weapon_already"] = "Ya tienes esta arma",
["threw_cannot_pickup"] = "¡Inventario lleno, no se puede recoger!",
["threw_pickup_prompt"] = "Pulsa E para recoger",
-- Key mapping
["keymap_showinventory"] = "Ver Inventario",
["keymap_showinventory"] = "Mostrar inventario",
-- Salary related
["received_salary"] = "Has recibido tu sueldo: $%s",
["received_help"] = "Has recibido su cheque de bienestar: $%s",
["company_nomoney"] = "La empresa en la que trabajas no tiene dinero para pagar tu sueldo",
["received_paycheck"] = "Recibió su paga",
["bank"] = "Banco",
["received_salary"] = "Has cobrado: $%s",
["received_help"] = "Has cobrado tu subsidio: $%s",
["company_nomoney"] = "La empresa para la que trabajas es demasiado pobre para pagarte el sueldo",
["received_paycheck"] = "Nómina recibida",
["bank"] = "Maze Bank",
["account_bank"] = "Banco",
["account_black_money"] = "Dinero Negro",
["account_black_money"] = "Dinero negro",
["account_money"] = "Efectivo",
["act_imp"] = "No se pudo realizar la acción.",
["in_vehicle"] = "Acción rechazada. El jugador se encuentra en un vehículo",
["not_in_vehicle"] = "Cannot Perform Action, Player isn't in a vehicle",
["act_imp"] = "No se puede realizar la acción",
["in_vehicle"] = "No se puede realizar la acción, el jugador está en un vehículo",
["not_in_vehicle"] = "No se puede realizar la acción, el jugador no está en un vehículo",
-- Commands
["command_bring"] = "Traer un jugador hacia ti",
["command_car"] = "Spawnear un vehículo",
["command_car_car"] = "Nombre del vehículo",
["command_bring"] = "Traer jugador hacia ti",
["command_car"] = "Generar un vehículo",
["command_car_car"] = "Modelo 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_repair"] = "Reparar tu vehiculo",
["command_repair_success"] = "Vehiculo reparado correctamente",
["command_repair_success_target"] = "Un administrador reparo tu vehiculo",
["command_clear"] = "Limpiar chat para ti",
["command_clearall"] = "Limpiar chat para todos los jugadores",
["command_clearinventory"] = "Limpiar el inventario del jugador",
["command_clearloadout"] = "Limpiar inventario de un jugador",
["command_freeze"] = "Congelar un jugador",
["command_unfreeze"] = "Descongelar un jugador",
["command_giveaccountmoney"] = "Dar dinero",
["command_giveaccountmoney_account"] = "Nombre de cuenta válido",
["command_cardel_radius"] = "Elimina todos los vehículos dentro del radio especificado",
["command_repair"] = "Reparar tu vehículo",
["command_repair_success"] = "Vehículo reparado con éxito",
["command_repair_success_target"] = "Un administrador reparó tu vehículo",
["command_clear"] = "Limpiar texto del chat",
["command_clearall"] = "Limpiar texto del chat para todos los jugadores",
["command_clearinventory"] = "Eliminar todos los objetos del inventario del jugador",
["command_clearloadout"] = "Eliminar todas las armas del equipamiento del jugador",
["command_freeze"] = "Congelar a un jugador",
["command_unfreeze"] = "Descongelar a un jugador",
["command_giveaccountmoney"] = "Dar dinero a una cuenta específica",
["command_giveaccountmoney_account"] = "Cuenta a la que añadir",
["command_giveaccountmoney_amount"] = "Cantidad a añadir",
["command_giveaccountmoney_invalid"] = "Nombre de cuenta no existente. [bank, money, black_money]",
["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_giveaccountmoney_invalid"] = "Nombre de cuenta inválido",
["command_removeaccountmoney"] = "Quitar dinero de una cuenta específica",
["command_removeaccountmoney_account"] = "Cuenta de la que quitar",
["command_removeaccountmoney_amount"] = "Cantidad a quitar",
["command_removeaccountmoney_invalid"] = "Nombre de cuenta inválido",
["command_giveitem"] = "Dar un objeto al jugador",
["command_giveitem_item"] = "Nombre del objeto",
["command_giveitem_count"] = "Cantidad",
["command_giveweapon"] = "Dar un arma al 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_giveweapon_ammo"] = "Cantidad de munición",
["command_giveweapon_hasalready"] = "El jugador ya tiene esta arma",
["command_giveweaponcomponent"] = "Dar componente de arma al jugador",
["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_goto"] = "Teletransportarte hacia un jugador",
["command_kill"] = "Matar un jugador",
["command_save"] = "Guardar la informacion de un jugador en la base de datos.",
["command_saveall"] = "Guardar toda la informacion de jugadores en la base de datos.",
["command_setaccountmoney"] = "Establecer el dinero de la cuenta para un jugador",
["command_setaccountmoney_amount"] = "Cantidad de dinero a establecer",
["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_giveweaponcomponent_invalid"] = "Componente de arma inválido",
["command_giveweaponcomponent_hasalready"] = "El jugador ya tiene este componente de arma",
["command_giveweaponcomponent_missingweapon"] = "El jugador no tiene esta arma",
["command_goto"] = "Teletransportarte a un jugador",
["command_kill"] = "Matar a un jugador",
["command_save"] = "Forzar guardado de datos de un jugador",
["command_saveall"] = "Forzar guardado de todos los datos de los jugadores",
["command_setaccountmoney"] = "Establecer el dinero en una cuenta específica",
["command_setaccountmoney_amount"] = "Cantidad",
["command_setcoords"] = "Teletransportar a coordenadas específicas",
["command_setcoords_x"] = "Valor X",
["command_setcoords_y"] = "Valor Y",
["command_setcoords_z"] = "Valor Z",
["command_setjob"] = "Establecer el trabajo de un jugador",
["command_setjob_job"] = "Nombre",
["command_setjob_grade"] = "Rango del trabajo",
["command_setjob_invalid"] = "El trabajo o el rango no son válidos",
["command_setgroup"] = "Establecer el grupo de un jugador",
["command_setjob_invalid"] = "El trabajo, el rango o ambos son inválidos",
["command_setgroup"] = "Establecer el grupo de permisos 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_argumentmismatch_string"] = "Invalid Argument #%s data type (passed number, wanted string)",
["commanderror_invaliditem"] = "Nombre del artículo no válido",
["commanderror_argumentmismatch"] = "Número de argumentos inválido (pasados %s, esperados %s)",
["commanderror_argumentmismatch_number"] = "Tipo de datos del argumento #%s inválido (pasado string, esperado número)",
["commanderror_argumentmismatch_string"] = "Tipo de datos del argumento #%s inválido (pasado número, esperado string)",
["commanderror_invaliditem"] = "Objeto inválido",
["commanderror_invalidweapon"] = "Arma inválida",
["commanderror_console"] = "Ese comando no se puede ejecutar desde la consola",
["commanderror_invalidcommand"] = "/%s ¡No es un comando válido!",
["commanderror_invalidplayerid"] = "No hay ningún jugador online con la ID especificada",
["commandgeneric_playerid"] = "ID del jugador",
["command_giveammo_noweapon_found"] = "%s no posee esa arma",
["commanderror_console"] = "El comando no se puede ejecutar desde la consola",
["commanderror_invalidcommand"] = "Comando inválido - /%s",
["commanderror_invalidplayerid"] = "El jugador especificado no está en línea",
["commandgeneric_playerid"] = "ID del servidor del jugador",
["commandgeneric_dimension"] = "Dimensión de destino",
["command_giveammo_noweapon_found"] = "%s no tiene esa arma",
["command_giveammo_weapon"] = "Nombre del arma",
["command_giveammo_ammo"] = "Cantidad de municion",
["command_giveammo_ammo"] = "Cantidad de munición",
["command_setdim"] = "Establecer la dimensión de un jugador",
["tpm_nowaypoint"] = "No hay punto de ruta establecido.",
["tpm_success"] = "Teletransportado con éxito",
["noclip_message"] = "Noclip ha sido %s",
["enabled"] = "~g~activado~s~",
["disabled"] = "~r~desactivado~s~",
-- Locale settings
["locale_digit_grouping_symbol"] = ",",
["locale_currency"] = "$%s",
["locale_digit_grouping_symbol"] = ".",
["locale_currency"] = "%s",
-- Weapons
-- Drug Wars DLC
["weapon_candycane"] = "Hacha de Caramelo ",
["weapon_acidpackage"] = "Paquete de Acido",
["weapon_pistolxm3"] = "Pistola WM 29",
["weapon_railgunxm3"] = "Fusil electromagnético",
-- Melee
["weapon_dagger"] = "Daga",
["weapon_bat"] = "Bate",
["weapon_battleaxe"] = "Hacha de combate",
["weapon_battleaxe"] = "Hacha de guerra",
["weapon_bottle"] = "Botella",
["weapon_crowbar"] = "Palanca",
["weapon_flashlight"] = "Linterna",
["weapon_golfclub"] = "Palo de Golf",
["weapon_golfclub"] = "Palo de golf",
["weapon_hammer"] = "Martillo",
["weapon_hatchet"] = "Hacha",
["weapon_hatchet"] = "Hachuela",
["weapon_knife"] = "Cuchillo",
["weapon_knuckle"] = "Puño Americano",
["weapon_knuckle"] = "Puño americano",
["weapon_machete"] = "Machete",
["weapon_nightstick"] = "Porra",
["weapon_wrench"] = "Llave Inglesa",
["weapon_poolcue"] = "Taco de Billar",
["weapon_stone_hatchet"] = "Hacha de Piedra",
["weapon_switchblade"] = "Navaja",
["weapon_wrench"] = "Llave inglesa",
["weapon_poolcue"] = "Taco de billar",
["weapon_stone_hatchet"] = "Hacha de piedra",
["weapon_switchblade"] = "Navaja automática",
-- Handguns
["weapon_appistol"] = "Pistola AP",
["weapon_ceramicpistol"] = "Pistola de Ceramica",
["weapon_combatpistol"] = "Pistola de 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 9mm",
["weapon_pistol_mk2"] = "Pistola MK2",
["weapon_appistol"] = "Pistola PA",
["weapon_ceramicpistol"] = "Pistola de cerámica",
["weapon_combatpistol"] = "Pistola de combate",
["weapon_doubleaction"] = "Revólver de doble acción",
["weapon_navyrevolver"] = "Revólver de la Marina",
["weapon_flaregun"] = "Pistola de bengalas",
["weapon_gadgetpistol"] = "Pistola de Cayo Perico",
["weapon_heavypistol"] = "Pistola pesada",
["weapon_revolver"] = "Revólver pesado",
["weapon_revolver_mk2"] = "Revólver pesado Mk2",
["weapon_marksmanpistol"] = "Pistola de tirador",
["weapon_pistol"] = "Pistola",
["weapon_pistol_mk2"] = "Pistola Mk2",
["weapon_pistol50"] = "Pistola .50",
["weapon_snspistol"] = "Pistola SNS",
["weapon_snspistol_mk2"] = "Pistola SNS MK2",
["weapon_stungun"] = "Taser",
["weapon_raypistol"] = "Up-N-Atomizer",
["weapon_vintagepistol"] = "Pistola Vintage",
["weapon_snspistol_mk2"] = "Pistola SNS Mk2",
["weapon_stungun"] = "Pistola eléctrica",
["weapon_raypistol"] = "Pistola de Rayos",
["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_assaultshotgun"] = "Escopeta de asalto",
["weapon_autoshotgun"] = "Escopeta automática",
["weapon_bullpupshotgun"] = "Escopeta bullpup",
["weapon_combatshotgun"] = "Escopeta de combate",
["weapon_dbshotgun"] = "Escopeta de dos cañones",
["weapon_heavyshotgun"] = "Escopeta pesada",
["weapon_musket"] = "Mosquete",
["weapon_pumpshotgun"] = "Escopeta de Bombeo",
["weapon_pumpshotgun_mk2"] = "Escopeta de Bombeo MK2",
["weapon_sawnoffshotgun"] = "Escopeta Recortada",
["weapon_pumpshotgun"] = "Escopeta de corredera",
["weapon_pumpshotgun_mk2"] = "Escopeta de corredera Mk2",
["weapon_sawnoffshotgun"] = "Escopeta recortada",
-- SMG & LMG
["weapon_assaultsmg"] = "Subfusil de Asalto",
["weapon_combatmg"] = "Ametralladora de Combate",
["weapon_combatmg_mk2"] = "Ametralladora MK2",
["weapon_combatpdw"] = "Subfusil PDW",
["weapon_gusenberg"] = "Subfusil de Barril",
["weapon_machinepistol"] = "Pistola Ametralladora",
["weapon_assaultsmg"] = "Subfusil de asalto",
["weapon_combatmg"] = "Ametralladora de combate",
["weapon_combatmg_mk2"] = "Ametralladora de combate Mk2",
["weapon_combatpdw"] = "PDW de combate",
["weapon_gusenberg"] = "Subfusil Gusenberg",
["weapon_machinepistol"] = "Pistola ametralladora",
["weapon_mg"] = "Ametralladora",
["weapon_microsmg"] = "Micro Subfusil",
["weapon_minismg"] = "Mini Subfusil",
["weapon_microsmg"] = "Microsubfusil",
["weapon_minismg"] = "Minisubfusil",
["weapon_smg"] = "Subfusil",
["weapon_smg_mk2"] = "Subfusil MK2",
["weapon_raycarbine"] = "Ametralladora de Rayos",
["weapon_smg_mk2"] = "Subfusil Mk2",
["weapon_raycarbine"] = "Carabina de Rayos",
["weapon_tecpistol"] = "Subfusil táctico",
-- 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_advancedrifle"] = "Fusil avanzado",
["weapon_assaultrifle"] = "Fusil de asalto",
["weapon_assaultrifle_mk2"] = "Fusil de asalto Mk2",
["weapon_bullpuprifle"] = "Fusil bullpup",
["weapon_bullpuprifle_mk2"] = "Fusil 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",
["weapon_heavyrifle"] = "Rifle Pesado",
["weapon_carbinerifle_mk2"] = "Carabina Mk2",
["weapon_compactrifle"] = "Fusil compacto",
["weapon_militaryrifle"] = "Fusil militar",
["weapon_specialcarbine"] = "Carabina especial",
["weapon_specialcarbine_mk2"] = "Carabina especial Mk2",
["weapon_heavyrifle"] = "Fusil pesado",
["weapon_battlerifle"] = "Fusil de combate",
-- 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",
["weapon_heavysniper"] = "Francotirador pesado",
["weapon_heavysniper_mk2"] = "Francotirador pesado Mk2",
["weapon_marksmanrifle"] = "Fusil de tirador",
["weapon_marksmanrifle_mk2"] = "Fusil de tirador Mk2",
["weapon_sniperrifle"] = "Fusil de francotirador",
-- Heavy / Launchers
["weapon_compactlauncher"] = "Lanzador Compacto",
["weapon_firework"] = "Lanzador de Fuegos Artificiales",
["weapon_compactlauncher"] = "Lanzagranadas compacto",
["weapon_firework"] = "Lanzador de pirotecnia",
["weapon_grenadelauncher"] = "Lanzagranadas",
["weapon_hominglauncher"] = "Lanzacohetes Guiado",
["weapon_hominglauncher"] = "Lanzacohetes teledirigido",
["weapon_minigun"] = "Minigun",
["weapon_railgun"] = "Cañón de riel",
["weapon_rpg"] = "Lanzador de cohetes",
["weapon_rayminigun"] = "Minigun de Rayos",
["weapon_rpg"] = "Lanzacohetes",
["weapon_rayminigun"] = "Ametralladora de rayos",
-- Criminal Enterprises DLC
["weapon_metaldetector"] = "Detector de metales",
["weapon_precisionrifle"] = "Fusil de precisión",
["weapon_tactilerifle"] = "Carabina de servicio",
-- Drug wars dlc
["weapon_candycane"] = "Bastón de caramelo",
["weapon_acidpackage"] = "Paquete de ácido",
["weapon_pistolxm3"] = "Pistola WM 29",
["weapon_railgunxm3"] = "Cañón de riel",
-- Chop Shop DLC
["weapon_snowlauncher"] = "Lanzador de nieve",
["weapon_hackingdevice"] = "Dispositivo de hackeo",
-- Bottom Dollar Bounties DLC
["weapon_stunrod"] = "Porra eléctrica",
-- Thrown
["weapon_ball"] = "Pelota de Beisbol",
["weapon_bzgas"] = "Gas Pimienta",
["weapon_ball"] = "Pelota de isbol",
["weapon_bzgas"] = "Gas BZ",
["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_petrolcan"] = "Bidón de gasolina",
["weapon_hazardcan"] = "Bidón de material peligroso",
["weapon_molotov"] = "Cóctel molotov",
["weapon_proxmine"] = "Mina de proximidad",
["weapon_pipebomb"] = "Bomba casera",
["weapon_snowball"] = "Bola de nieve",
["weapon_stickybomb"] = "C4",
["weapon_smokegrenade"] = "Granada de Humo",
["weapon_stickybomb"] = "Bomba lapa",
["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_digiscanner"] = "Escáner digital",
["weapon_garbagebag"] = "Bolsa de basura",
["weapon_handcuffs"] = "Esposas",
["gadget_nightvision"] = "Visión nocturna",
["gadget_parachute"] = "Paracaídas",
-- 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_knuckle_base"] = "Modelo base",
["component_knuckle_pimp"] = "El Chulo",
["component_knuckle_ballas"] = "Los Ballas",
["component_knuckle_dollar"] = "El Buscavidas",
["component_knuckle_diamond"] = "La Roca",
["component_knuckle_hate"] = "El Odiador",
["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_luxary_finish"] = "Acabado de arma de lujo",
["component_handle_default"] = "Mango Default",
["component_handle_vip"] = "Mango VIP",
["component_handle_bodyguard"] = "Mango de Guardaespaldas",
["component_handle_default"] = "Empuñadura por defecto",
["component_handle_vip"] = "Empuñadura VIP",
["component_handle_bodyguard"] = "Empuñadura de guardaespaldas",
["component_vip_finish"] = "Acabado VIP",
["component_bodyguard_finish"] = "Acabado Guardaespaldas",
["component_bodyguard_finish"] = "Acabado de guardaespaldas",
["component_camo_finish"] = "Camuflaje Digital",
["component_camo_finish2"] = "Camuflaje Pincelada",
["component_camo_finish3"] = "Camuflaje Bosque",
["component_camo_finish4"] = "Camuflaje Calavera",
["component_camo_finish"] = "Camuflaje digital",
["component_camo_finish2"] = "Camuflaje pincelada",
["component_camo_finish3"] = "Camuflaje boscoso",
["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_finish7"] = "Camuflaje leopardo",
["component_camo_finish8"] = "Camuflaje cebra",
["component_camo_finish9"] = "Camuflaje geométrico",
["component_camo_finish10"] = "Camuflaje Boom",
["component_camo_finish11"] = "Camuflaje Patriotico",
["component_camo_finish11"] = "Camuflaje patriótico",
["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_camo_slide_finish"] = "Camuflaje digital (corredera)",
["component_camo_slide_finish2"] = "Camuflaje pincelada (corredera)",
["component_camo_slide_finish3"] = "Camuflaje boscoso (corredera)",
["component_camo_slide_finish4"] = "Camuflaje calavera (corredera)",
["component_camo_slide_finish5"] = "Camuflaje Sessanta Nove (corredera)",
["component_camo_slide_finish6"] = "Camuflaje Perseo (corredera)",
["component_camo_slide_finish7"] = "Camuflaje leopardo (corredera)",
["component_camo_slide_finish8"] = "Camuflaje cebra (corredera)",
["component_camo_slide_finish9"] = "Camuflaje geométrico (corredera)",
["component_camo_slide_finish10"] = "Camuflaje Boom (corredera)",
["component_camo_slide_finish11"] = "Camuflaje patriótico (corredera)",
["component_clip_default"] = "Cargador Default",
["component_clip_extended"] = "Cargador Extendido",
["component_clip_drum"] = "Cargador Barril",
["component_clip_box"] = "Caja de Cargador",
["component_clip_default"] = "Cargador por defecto",
["component_clip_extended"] = "Cargador ampliado",
["component_clip_drum"] = "Cargador de tambor",
["component_clip_box"] = "Cargador de caja",
["component_scope_holo"] = "Mira Holográfica",
["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_scope_holo"] = "Mira holográfica",
["component_scope_small"] = "Mira pequeña",
["component_scope_medium"] = "Mira mediana",
["component_scope_large"] = "Mira telescópica",
["component_scope"] = "Mira óptica",
["component_scope_advanced"] = "Mira avanzada",
["component_ironsights"] = "Miras de hierro",
["component_suppressor"] = "Silenciador",
["component_compensator"] = "Estabilizador",
["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_muzzle_flat"] = "Freno de boca plano",
["component_muzzle_tactical"] = "Freno de boca táctico",
["component_muzzle_fat"] = "Freno de boca grueso",
["component_muzzle_precision"] = "Freno de boca de precisión",
["component_muzzle_heavy"] = "Freno de boca pesado",
["component_muzzle_slanted"] = "Freno de boca inclinado",
["component_muzzle_split"] = "Freno de boca dividido",
["component_muzzle_squared"] = "Freno de boca cuadrado",
["component_flashlight"] = "Linterna",
["component_grip"] = "Agarre",
["component_grip"] = "Empuñadura",
["component_barrel_default"] = "Barril Por Defecto",
["component_barrel_heavy"] = "Barril Pesado",
["component_barrel_default"] = "Cañón por defecto",
["component_barrel_heavy"] = "Cañón 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_ammo_tracer"] = "Munición trazadora",
["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",
["component_ammo_explosive"] = "Munición explosiva perforante",
["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",
["component_shells_default"] = "Cartuchos por defecto",
["component_shells_incendiary"] = "Cartuchos Aliento de dragón",
["component_shells_armor"] = "Cartuchos de postas de acero",
["component_shells_hollowpoint"] = "Cartuchos de perdigones expansivos",
["component_shells_explosive"] = "Cartuchos de postas explosivas",
-- 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)",
["ammo_rounds"] = "proyectil(es)",
["ammo_shells"] = "cartucho(s)",
["ammo_charge"] = "carga(s)",
["ammo_petrol"] = "litros de combustible",
["ammo_firework"] = "cohete(s) de pirotecnia",
["ammo_rockets"] = "cohete(s)",
["ammo_grenadelauncher"] = "granada(s)",
["ammo_grenade"] = "granada(s)",
["ammo_stickybomb"] = "bomba(s) lapa",
["ammo_pipebomb"] = "bomba(s) casera",
["ammo_smokebomb"] = "bomba(s) de humo",
["ammo_molotov"] = "cóctel(es) molotov",
["ammo_proxmine"] = "mina(s) de proximidad",
["ammo_bzgas"] = "bote(s) de gas",
["ammo_ball"] = "pelota(s)",
["ammo_snowball"] = "bola(s) de nieve",
["ammo_flare"] = "bengala(s)",
["ammo_flaregun"] = "bengala(s)",
-- Weapon Tints
["tint_default"] = "Skin común",
["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",
["tint_default"] = "Diseño por defecto",
["tint_green"] = "Diseño verde",
["tint_gold"] = "Diseño dorado",
["tint_pink"] = "Diseño rosa",
["tint_army"] = "Diseño militar",
["tint_lspd"] = "Diseño LSPD",
["tint_orange"] = "Diseño naranja",
["tint_platinum"] = "Diseño platino",
-- MK2 Weapon Tints
["tint_classic_black"] = "negro clásico",
["tint_classic_gray"] = "gris clásico",
["tint_classic_two_tone"] = "dos tonos clásicos",
["tint_classic_white"] = "blanco clásico",
["tint_classic_beige"] = "beige clásico",
["tint_classic_green"] = "verde clásico",
["tint_classic_blue"] = "azul clásico",
["tint_classic_earth"] = "tierra clásica",
["tint_classic_brown_black"] = "marrón negro clásico",
["tint_contrast_red"] = "rojo de contraste",
["tint_contrast_blue"] = "azul de contraste",
["tint_contrast_yellow"] = "amarillo de contraste",
["tint_contrast_orange"] = "naranja de contraste",
["tint_bold_pink"] = "rosa atrevida",
["tint_bold_purple_yellow"] = "púrpura amarilla atrevida",
["tint_bold_orange"] = "naranja atrevido",
["tint_bold_green_purple"] = "verde púrpura atrevido",
["tint_bold_red_feat"] = "rojo atrevido feat",
["tint_bold_green_feat"] = "verde atrevido feat",
["tint_bold_cyan_feat"] = "cian atrevido feat",
["tint_bold_yellow_feat"] = "amarillo atrevido feat",
["tint_bold_red_white"] = "rojo blanco atrevido",
["tint_bold_blue_white"] = "azul blanco atrevido",
["tint_metallic_gold"] = "oro metálico",
["tint_metallic_platinum"] = "platino metálico",
["tint_metallic_gray_lilac"] = "gris lila metálico",
["tint_metallic_purple_lime"] = "púrpura lima metálico",
["tint_metallic_red"] = "rojo metálico",
["tint_metallic_green"] = "verde metálico",
["tint_metallic_blue"] = "azul metálico",
["tint_metallic_white_aqua"] = "blanco aqua metálico",
["tint_metallic_red_yellow"] = "rojo amarillo metálico",
["tint_classic_black"] = "Negro clásico",
["tint_classic_gray"] = "Gris clásico",
["tint_classic_two_tone"] = "Dos tonos clásico",
["tint_classic_white"] = "Blanco clásico",
["tint_classic_beige"] = "Beige clásico",
["tint_classic_green"] = "Verde clásico",
["tint_classic_blue"] = "Azul clásico",
["tint_classic_earth"] = "Tierra clásico",
["tint_classic_brown_black"] = "Marrón y negro clásico",
["tint_contrast_red"] = "Rojo contraste",
["tint_contrast_blue"] = "Azul contraste",
["tint_contrast_yellow"] = "Amarillo contraste",
["tint_contrast_orange"] = "Naranja contraste",
["tint_bold_pink"] = "Rosa intenso",
["tint_bold_purple_yellow"] = "Morado y amarillo intenso",
["tint_bold_orange"] = "Naranja intenso",
["tint_bold_green_purple"] = "Verde y morado intenso",
["tint_bold_red_feat"] = "Rojo intenso especial",
["tint_bold_green_feat"] = "Verde intenso especial",
["tint_bold_cyan_feat"] = "Cian intenso especial",
["tint_bold_yellow_feat"] = "Amarillo intenso especial",
["tint_bold_red_white"] = "Rojo y blanco intenso",
["tint_bold_blue_white"] = "Azul y blanco intenso",
["tint_metallic_gold"] = "Dorado metálico",
["tint_metallic_platinum"] = "Platino metálico",
["tint_metallic_gray_lilac"] = "Gris lila metálico",
["tint_metallic_purple_lime"] = "Morado lima metálico",
["tint_metallic_red"] = "Rojo metálico",
["tint_metallic_green"] = "Verde metálico",
["tint_metallic_blue"] = "Azul metálico",
["tint_metallic_white_aqua"] = "Blanco aguamarina metálico",
["tint_metallic_red_yellow"] = "Rojo y amarillo metálico",
}
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["fi"] = {
return {
-- Inventory
["inventory"] = "Reppu %s / %s",
["use"] = "Käytä",
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["fr"] = {
return {
-- Inventory
["inventory"] = "Inventaire ( Poids %s / %s )",
["use"] = "Utiliser",
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["he"] = {
return {
-- Inventory
["inventory"] = "מלאי ( משקל %s / %s )",
["use"] = "השתמש",
+4 -4
View File
@@ -1,4 +1,4 @@
Locales["hu"] = {
return {
-- Inventory
["inventory"] = "Inventory ( Súly %s / %s )",
["use"] = "Használ",
@@ -229,10 +229,10 @@ Locales["hu"] = {
["weapon_tactilerifle"] = "Service Carbine",
-- Drug Wars DLC
["weapon_candycane"] = "Candy Cane", -- not translated
["weapon_candycane"] = "Candy Cane", -- not translated
["weapon_acidpackage"] = "Acid Package", -- not translated
["weapon_pistolxm3"] = "WM 29 Pistol", -- not translated
["weapon_railgunxm3"] = "Railgun", -- not translated
["weapon_pistolxm3"] = "WM 29 Pistol", -- not translated
["weapon_railgunxm3"] = "Railgun", -- not translated
-- Thrown
["weapon_ball"] = "Baseball",
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["id"] = {
return {
-- Inventory
["inventory"] = "Inventaris ( Berat %s / %s )",
["use"] = "Gunakan",
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["it"] = {
return {
-- Inventory
["inventory"] = "Inventario ( Peso %s / %s )",
["use"] = "Usa",
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["nl"] = {
return {
-- Inventory
["inventory"] = "Inventaris ( Gewicht %s / %s )",
["use"] = "Gebruik",
+4 -4
View File
@@ -1,4 +1,4 @@
Locales["pl"] = {
return {
-- Inventory
["inventory"] = "ekwipunek %s / %s",
["use"] = "użyj",
@@ -202,10 +202,10 @@ Locales["pl"] = {
["component_luxary_finish"] = "luksusowe wykończenie broni",
-- Drug Wars DLC
["weapon_candycane"] = "Candy Cane", -- not translated
["weapon_candycane"] = "Candy Cane", -- not translated
["weapon_acidpackage"] = "Acid Package", -- not translated
["weapon_pistolxm3"] = "WM 29 Pistol", -- not translated
["weapon_railgunxm3"] = "Railgun", -- not translated
["weapon_pistolxm3"] = "WM 29 Pistol", -- not translated
["weapon_railgunxm3"] = "Railgun", -- not translated
-- Weapon Ammo
["ammo_rounds"] = "nabój/oi",
+4 -4
View File
@@ -1,4 +1,4 @@
Locales["sl"] = {
return {
-- Inventory
["inventory"] = "Shramba ( Teza %s / %s )",
["use"] = "Uporabi",
@@ -229,10 +229,10 @@ Locales["sl"] = {
["weapon_tactilerifle"] = "Service Carbine",
-- Drug Wars DLC
["weapon_candycane"] = "Candy Cane", -- not translated
["weapon_candycane"] = "Candy Cane", -- not translated
["weapon_acidpackage"] = "Acid Package", -- not translated
["weapon_pistolxm3"] = "WM 29 Pistol", -- not translated
["weapon_railgunxm3"] = "Railgun", -- not translated
["weapon_pistolxm3"] = "WM 29 Pistol", -- not translated
["weapon_railgunxm3"] = "Railgun", -- not translated
-- Thrown
["weapon_ball"] = "Baseball",
+4 -4
View File
@@ -1,4 +1,4 @@
Locales["sr"] = {
return {
-- Inventory
["inventory"] = "Inventar ( Težina %s / %s )",
["use"] = "Koristi",
@@ -229,10 +229,10 @@ Locales["sr"] = {
["weapon_tactilerifle"] = "Service Carbine",
-- Drug Wars DLC
["weapon_candycane"] = "Candy Cane", -- not translated
["weapon_candycane"] = "Candy Cane", -- not translated
["weapon_acidpackage"] = "Acid Package", -- not translated
["weapon_pistolxm3"] = "WM 29 Pistol", -- not translated
["weapon_railgunxm3"] = "Railgun", -- not translated
["weapon_pistolxm3"] = "WM 29 Pistol", -- not translated
["weapon_railgunxm3"] = "Railgun", -- not translated
-- Thrown
["weapon_ball"] = "Baseball",
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["sv"] = {
return {
-- Inventory
["inventory"] = "Inventory ( Vikt %s / %s )",
["use"] = "Använd",
+8 -8
View File
@@ -1,4 +1,4 @@
Locales["tr"] = {
return {
-- Inventory
["inventory"] = "Envanter ( Ağırlık %s / %s )",
["use"] = "Kullan",
@@ -36,10 +36,10 @@ Locales["tr"] = {
["threw_weapon_already"] = "Bu Silaha Zaten Sahipsiniz",
["threw_cannot_pickup"] = "Envanter Dolu, Alınamaz!",
["threw_pickup_prompt"] = "Almak İçin E'ye Basın",
-- Key mapping
["keymap_showinventory"] = "Envanteri Göster",
-- Salary related
["received_salary"] = "Maaşınız Ödendi: $%s",
["received_help"] = "Yardım Çekiniz Ödendi: $%s",
@@ -49,11 +49,11 @@ Locales["tr"] = {
["account_bank"] = "Banka",
["account_black_money"] = "Kirli Para",
["account_money"] = "Nakit",
["act_imp"] = "İşlem Yapılamaz",
["in_vehicle"] = "İşlem Yapılamaz, Oyuncu Araçta",
["not_in_vehicle"] = "İşlem Yapılamaz, Oyuncu Araçta Değil",
-- Commands
["command_bring"] = "Oyuncuyu Yanınıza Getir",
["command_car"] = "Araç Spawn Et",
@@ -119,14 +119,14 @@ Locales["tr"] = {
["command_giveammo_ammo"] = "Mermi Miktarı",
["tpm_nowaypoint"] = "Hiçbir Yol İşareti Ayarlanmadı.",
["tpm_success"] = "Başarıyla Teleport Edildi",
["noclip_message"] = "Noclip %s Yapıldı",
["enabled"] = "~g~Aktif Edildi~s~",
["disabled"] = "~r~Pasif Edildi~s~",
-- Locale settings
["locale_digit_grouping_symbol"] = ",",
["locale_currency"] = "£%s",
["locale_currency"] = "£%s",
-- Silahlar
+4 -4
View File
@@ -1,4 +1,4 @@
Locales["zh-cn"] = {
return {
-- Inventory
["inventory"] = "背包 %s / %s",
["use"] = "使用",
@@ -229,10 +229,10 @@ Locales["zh-cn"] = {
["weapon_tactilerifle"] = "制式卡宾步枪",
-- Drug Wars DLC
["weapon_candycane"] = "Candy Cane", -- not translated
["weapon_candycane"] = "Candy Cane", -- not translated
["weapon_acidpackage"] = "Acid Package", -- not translated
["weapon_pistolxm3"] = "WM 29 Pistol", -- not translated
["weapon_railgunxm3"] = "Railgun", -- not translated
["weapon_pistolxm3"] = "WM 29 Pistol", -- not translated
["weapon_railgunxm3"] = "Railgun", -- not translated
-- Thrown
["weapon_ball"] = "棒球",
@@ -91,6 +91,11 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory,
return self.paycheckEnabled
end
---@return boolean
function self.isAdmin()
return Core.IsPlayerAdmin(self.source)
end
---@param coordinates vector4 | vector3 | table
---@return nil
function self.setCoords(coordinates)
@@ -455,6 +460,12 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory,
return self.weight
end
---@return number
function self.getSource()
return self.source
end
self.getPlayerId = self.getSource
---@return number
function self.getMaxWeight()
return self.maxWeight
@@ -944,3 +955,17 @@ function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory,
return self
end
local function runStaticPlayerMethod(src, method, ...)
local xPlayer = ESX.Players[src]
if not xPlayer then
return
end
if not ESX.IsFunctionReference(xPlayer[method]) then
error(("Attempted to call invalid method on playerId %s: %s"):format(src, method))
end
return xPlayer[method](...)
end
exports("RunStaticPlayerMethod", runStaticPlayerMethod)
@@ -0,0 +1,237 @@
---@class CVehicleData
---@field plate string
---@field netId number
---@field entity number
---@field modelHash number
---@field owner string
---@class CExtendedVehicle
---@field plate string
---@field isValid fun(self:CExtendedVehicle):boolean
---@field new fun(owner:string, plate:string, coords:vector4): CExtendedVehicle?
---@field getFromPlate fun(plate:string):CExtendedVehicle?
---@field getPlate fun(self:CExtendedVehicle):string?
---@field getNetId fun(self:CExtendedVehicle):number?
---@field getEntity fun(self:CExtendedVehicle):number?
---@field getModelHash fun(self:CExtendedVehicle):number?
---@field getOwner fun(self:CExtendedVehicle):string?
---@field setPlate fun(self:CExtendedVehicle, newPlate:string):boolean
---@field setProps fun(self:CExtendedVehicle, newProps:table):boolean
---@field setOwner fun(self:CExtendedVehicle, newOwner:string):boolean
---@field delete fun(self:CExtendedVehicle, garageName:string?, isImpound:boolean?):nil
Core.vehicleClass = {
plate = "",
new = function(owner, plate, coords)
assert(type(owner) == "string", "Expected 'owner' to be a string")
assert(type(plate) == "string", "Expected 'plate' to be a string")
assert(type(coords) == "vector4", "Expected 'coords' to be a vector4")
local xVehicle = Core.vehicleClass.getFromPlate(plate)
if xVehicle then
return xVehicle
end
local vehicleProps = MySQL.scalar.await("SELECT `vehicle` FROM `owned_vehicles` WHERE `stored` = true AND `owner` = ? AND `plate` = ? LIMIT 1", { owner, plate })
if not vehicleProps then
return
end
vehicleProps = json.decode(vehicleProps)
if type(vehicleProps.model) ~= "number" then
vehicleProps.model = joaat(vehicleProps.model)
end
local netId = ESX.OneSync.SpawnVehicle(vehicleProps.model, coords.xyz, coords.w, vehicleProps)
if not netId then
return
end
local entity = NetworkGetEntityFromNetworkId(netId)
if entity <= 0 then
return
end
Entity(entity).state:set("owner", owner, false)
Entity(entity).state:set("plate", plate, false)
---@type CVehicleData
local vehicleData = {
plate = plate,
entity = entity,
netId = netId,
modelHash = vehicleProps.model,
owner = owner,
}
Core.vehicles[plate] = vehicleData
MySQL.update.await("UPDATE `owned_vehicles` SET `stored` = false WHERE `owner` = ? AND `plate` = ?", { owner, plate })
local obj = table.clone(Core.vehicleClass)
obj.plate = plate
TriggerEvent("esx:createdExtendedVehicle", obj)
return obj
end,
getFromPlate = function(plate)
assert(type(plate) == "string", "Expected 'plate' to be a string")
if Core.vehicles[plate] then
local obj = table.clone(Core.vehicleClass)
obj.plate = plate
if obj:isValid() then
return obj
end
end
end,
isValid = function(self)
local vehicleData = Core.vehicles[self.plate]
if not vehicleData then
return false
end
local entity = NetworkGetEntityFromNetworkId(vehicleData.netId)
if entity <= 0 or Entity(entity).state.owner ~= vehicleData.owner or Entity(entity).state.plate ~= vehicleData.plate then
self:delete()
return false
end
vehicleData.entity = entity
return true
end,
getNetId = function(self)
if not self:isValid() then
return
end
return Core.vehicles[self.plate].netId
end,
getEntity = function(self)
if not self:isValid() then
return
end
return Core.vehicles[self.plate].entity
end,
getPlate = function(self)
if not self:isValid() then
return
end
return Core.vehicles[self.plate].plate
end,
getModelHash = function(self)
if not self:isValid() then
return
end
return Core.vehicles[self.plate].modelHash
end,
getOwner = function(self)
if not self:isValid() then
return
end
return Core.vehicles[self.plate].owner
end,
setPlate = function(self, newPlate)
if not self:isValid() then
return false
end
assert(type(newPlate) == "string", "Expected 'plate' to be a string")
local vehicleData = Core.vehicles[self.plate]
local affectedRows = MySQL.update.await("UPDATE `owned_vehicles` SET `plate` = ? WHERE `plate` = ? AND `owner` = ?", { newPlate, vehicleData.plate, vehicleData.owner })
if affectedRows <= 0 then
self:delete()
return false
end
Entity(vehicleData.entity).state:set("plate", newPlate, false)
SetVehicleNumberPlateText(vehicleData.entity, newPlate)
local oldPlate = vehicleData.plate
vehicleData.plate = newPlate
Core.vehicles[newPlate] = table.clone(vehicleData)
Core.vehicles[oldPlate] = nil
TriggerEvent("esx:changedExtendedVehiclePlate", vehicleData.plate, oldPlate)
Wait(0)
return true
end,
setProps = function(self, newProps)
if not self:isValid() then
return false
end
assert(type(newProps) == "table", "Expected 'props' to be a table")
local vehicleData = Core.vehicles[self.plate]
local affectedRows = MySQL.update.await("UPDATE `owned_vehicles` SET `vehicle` = ? WHERE `plate` = ? AND `owner` = ?", json.encode(newProps), vehicleData.plate, vehicleData.owner)
if affectedRows <= 0 then
self:delete()
return false
end
Entity(vehicleData.entity).state:set("VehicleProperties", newProps, true)
return true
end,
setOwner = function(self, newOwner)
if not self:isValid() then
return false
end
assert(type(newOwner) == "string", "Expected 'owner' to be a string")
local vehicleData = Core.vehicles[self.plate]
if vehicleData.owner == newOwner then
return true
end
local affectedRows = MySQL.update.await("UPDATE `owned_vehicles` SET `owner` = ? WHERE owner = ? AND `plate` = ?", { newOwner, vehicleData.owner, vehicleData.plate })
if affectedRows <= 0 then
self:delete()
return false
end
Entity(vehicleData.entity).state:set("owner", newOwner, false)
vehicleData.owner = newOwner
return true
end,
delete = function(self, garageName, isImpound)
if type(garageName) ~= "string" then
garageName = nil
end
if type(isImpound) ~= "boolean" then
isImpound = false
end
local vehicleData = Core.vehicles[self.plate]
if not vehicleData then
return
end
local entity = NetworkGetEntityFromNetworkId(vehicleData.netId)
if entity >= 0 and Entity(entity).state.owner == vehicleData.owner then
DeleteEntity(vehicleData.entity)
end
local query = "UPDATE `owned_vehicles` SET `stored` = true WHERE `plate` = ? AND `owner` = ?"
local queryParams = { vehicleData.plate, vehicleData.owner }
if garageName then
if isImpound then
query = "UPDATE `owned_vehicles` SET `stored` = true, `parking` = NULL, `pound` = ? WHERE `plate` = ? AND `owner` = ?"
else
query = "UPDATE `owned_vehicles` SET `stored` = true, `pound` = NULL, `parking` = ? WHERE `plate` = ? AND `owner` = ?"
end
queryParams = { garageName, vehicleData.plate, vehicleData.owner }
end
MySQL.update.await(query, queryParams)
TriggerEvent("esx:deletedExtendedVehicle", self)
Core.vehicles[self.plate] = nil
end,
}
+2
View File
@@ -11,6 +11,8 @@ Core.PlayerFunctionOverrides = {}
Core.DatabaseConnected = false
Core.playersByIdentifier = {}
---@type table<string, CVehicleData>
Core.vehicles = {}
Core.vehicleTypesByModel = {}
RegisterNetEvent("esx:onPlayerSpawn", function()
+63 -11
View File
@@ -62,7 +62,7 @@ function ESX.RegisterCommand(name, group, cb, allowConsole, suggestion)
local command = Core.RegisteredCommands[name]
if not command.allowConsole and playerId == 0 then
print(("[^3WARNING^7] ^5%s"):format(TranslateCap("commanderror_console")))
print(("[^3WARNING^7] ^5%s^0"):format(TranslateCap("commanderror_console")))
else
local xPlayer, error = ESX.Players[playerId], nil
@@ -358,6 +358,18 @@ function ESX.GetPlayerFromIdentifier(identifier)
return Core.playersByIdentifier[identifier]
end
---@param identifier string
---@return number playerId
function ESX.GetPlayerIdFromIdentifier(identifier)
return Core.playersByIdentifier[identifier]?.source
end
---@param source number
---@return boolean
function ESX.IsPlayerLoaded(source)
return ESX.Players[source] ~= nil
end
---@param playerId number | string
---@return string
function ESX.GetIdentifier(playerId)
@@ -374,19 +386,37 @@ end
---@param model string|number
---@param player number
---@param cb function
---@param cb function?
---@return string?
---@diagnostic disable-next-line: duplicate-set-field
function ESX.GetVehicleType(model, player, cb)
if cb and not ESX.IsFunctionReference(cb) then
error("Invalid callback function")
end
local promise = not cb and promise.new()
local function resolve(result)
if promise then
promise:resolve(result)
elseif cb then
cb(result)
end
end
model = type(model) == "string" and joaat(model) or model
if Core.vehicleTypesByModel[model] then
return cb(Core.vehicleTypesByModel[model])
return resolve(Core.vehicleTypesByModel[model])
end
ESX.TriggerClientCallback(player, "esx:GetVehicleType", function(vehicleType)
Core.vehicleTypesByModel[model] = vehicleType
cb(vehicleType)
resolve(vehicleType)
end, model)
if promise then
return Citizen.Await(promise)
end
end
---@param name string
@@ -433,6 +463,11 @@ end
---@param fields table
---@return nil
function ESX.DiscordLogFields(name, title, color, fields)
for i = 1, #fields do
local field = fields[i]
field.value = tostring(field.value)
end
local webHook = Config.DiscordLogs.Webhooks[name] or Config.DiscordLogs.Webhooks.default
local embedData = {
{
@@ -495,7 +530,7 @@ function ESX.RefreshJobs()
if not Jobs then
-- Fallback data, if no jobs exist
ESX.Jobs["unemployed"] = { label = "Unemployed", grades = { ["0"] = { grade = 0, label = "Unemployed", salary = 200, skin_male = {}, skin_female = {} } } }
ESX.Jobs["unemployed"] = { name = "unemployed", label = "Unemployed", whitelisted = false, grades = { ["0"] = { grade = 0, name = "unemployed", label = "Unemployed", salary = 200, skin_male = {}, skin_female = {} } } }
else
ESX.Jobs = Jobs
end
@@ -609,14 +644,31 @@ function ESX.DoesJobExist(job, grade)
return (ESX.Jobs[job] and ESX.Jobs[job].grades[tostring(grade)] ~= nil) or false
end
---@param playerId string | number
---@param playerSrc number
---@return boolean
function Core.IsPlayerAdmin(playerId)
playerId = tostring(playerId)
if (IsPlayerAceAllowed(playerId, "command") or GetConvar("sv_lan", "") == "true") then
function Core.IsPlayerAdmin(playerSrc)
if type(playerSrc) ~= "number" then
return false
end
if IsPlayerAceAllowed(playerSrc --[[@as string]], "command") or GetConvar("sv_lan", "") == "true" then
return true
end
local xPlayer = ESX.Players[playerId]
return (xPlayer and Config.AdminGroups[xPlayer.group] and true) or false
local xPlayer = ESX.GetPlayerFromId(playerSrc)
return xPlayer and Config.AdminGroups[xPlayer.getGroup()] or false
end
---@param owner string
---@param plate string
---@param coords vector4
---@return CExtendedVehicle?
function ESX.CreateExtendedVehicle(owner, plate, coords)
return Core.vehicleClass.new(owner, plate, coords)
end
---@param plate string
---@return CExtendedVehicle?
function ESX.GetExtendedVehicleFromPlate(plate)
return Core.vehicleClass.getFromPlate(plate)
end
+63 -26
View File
@@ -67,6 +67,46 @@ local function onPlayerJoined(playerId)
end
end
---@param playerId number
---@param reason string
---@param cb function?
local function onPlayerDropped(playerId, reason, cb)
local xPlayer = ESX.GetPlayerFromId(playerId)
if not xPlayer then
return
end
TriggerEvent("esx:playerDropped", playerId, reason)
local job = xPlayer.getJob().name
local currentJob = Core.JobsPlayerCount[job]
Core.JobsPlayerCount[job] = ((currentJob and currentJob > 0) and currentJob or 1) - 1
GlobalState[("%s:count"):format(job)] = Core.JobsPlayerCount[job]
Core.playersByIdentifier[xPlayer.identifier] = nil
local p = not cb and promise:new()
local function resolve()
if cb then
return cb()
elseif(p) then
return p:resolve()
end
end
Core.SavePlayer(xPlayer, function()
GlobalState["playerCount"] = GlobalState["playerCount"] - 1
ESX.Players[playerId] = nil
resolve()
end)
if p then
return Citizen.Await(p)
end
end
AddEventHandler("esx:onPlayerDropped", onPlayerDropped)
if Config.Multichar then
AddEventHandler("esx:onPlayerJoined", function(src, char, data)
while not next(ESX.Jobs) do
@@ -115,17 +155,24 @@ if not Config.Multichar then
return deferrals.done("[ESX] OxMySQL Was Unable To Connect to your database. Please make sure it is turned on and correctly configured in your server.cfg")
end
if identifier then
if ESX.GetPlayerFromIdentifier(identifier) then
return deferrals.done(
("[ESX] 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
return deferrals.done()
end
else
if not identifier then
return deferrals.done("[ESX] 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
local xPlayer = ESX.GetPlayerFromIdentifier(identifier)
if not xPlayer then
return deferrals.done()
end
if DoesPlayerExist(xPlayer.source --[[@as string]]) then
return deferrals.done(
("[ESX] 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)
)
end
deferrals.update(("[ESX] Cleaning stale player entry..."):format(identifier))
onPlayerDropped(xPlayer.source, "esx_stale_player_obj")
deferrals.done()
end)
end
@@ -311,24 +358,9 @@ AddEventHandler("chatMessage", function(playerId, _, message)
end
end)
---@param reason string
AddEventHandler("playerDropped", function(reason)
local playerId = source
local xPlayer = ESX.GetPlayerFromId(playerId)
if xPlayer then
TriggerEvent("esx:playerDropped", playerId, reason)
local job = xPlayer.getJob().name
local currentJob = Core.JobsPlayerCount[job]
Core.JobsPlayerCount[job] = ((currentJob and currentJob > 0) and currentJob or 1) - 1
GlobalState[("%s:count"):format(job)] = Core.JobsPlayerCount[job]
Core.playersByIdentifier[xPlayer.identifier] = nil
Core.SavePlayer(xPlayer, function()
GlobalState["playerCount"] = GlobalState["playerCount"] - 1
ESX.Players[playerId] = nil
end)
end
onPlayerDropped(source --[[@as number]], reason)
end)
AddEventHandler("esx:playerLoaded", function(_, xPlayer)
@@ -353,6 +385,11 @@ end)
AddEventHandler("esx:playerLogout", function(playerId, cb)
local xPlayer = ESX.GetPlayerFromId(playerId)
local job = xPlayer.getJob().name
Core.JobsPlayerCount[job] = Core.JobsPlayerCount[job] - 1
GlobalState[("%s:count"):format(job)] = Core.JobsPlayerCount[job]
if xPlayer then
TriggerEvent("esx:playerDropped", playerId)
+34 -2
View File
@@ -33,11 +33,17 @@ function Callbacks:Execute(cb, ...)
end
function Callbacks:Trigger(player, event, cb, invoker, ...)
self.requests[self.id] = cb
self.requests[self.id] = {
await = type(cb) == "boolean",
cb = cb or promise:new()
}
local table = self.requests[self.id]
TriggerClientEvent("esx:triggerClientCallback", player, event, self.id, invoker, ...)
self.id += 1
return table.cb
end
function Callbacks:ServerRecieve(player, event, requestId, invoker, ...)
@@ -64,8 +70,12 @@ function Callbacks:RecieveClient(requestId, invoker, ...)
local callback = self.requests[self.currentId]
self:Execute(callback, ...)
self.requests[requestId] = nil
if callback.await then
callback.cb:resolve({ ... })
else
self:Execute(callback.cb, ...)
end
end
-- =============================================
@@ -83,6 +93,28 @@ function ESX.TriggerClientCallback(player, eventName, callback, ...)
Callbacks:Trigger(player, eventName, callback, invoker, ...)
end
---@param player number playerId
---@param eventName string
---@param ... any
---@return any
function ESX.AwaitClientCallback(player, eventName, ...)
local invokingResource = GetInvokingResource()
local invoker = (invokingResource and invokingResource ~= "Unknown") and invokingResource or "es_extended"
local p = Callbacks:Trigger(player, eventName, false, invoker, ...)
if not p then return end
SetTimeout(15000, function()
if p.state == "pending" then
p:reject("Server Callback Timed Out")
end
end)
Citizen.Await(p)
return table.unpack(p.value)
end
---@param eventName string
---@param callback function
---@return nil
@@ -72,10 +72,10 @@ function ESX.CreateJob(name, label, grades)
{ query = 'INSERT INTO jobs (name, label) VALUES (?, ?)', values = { name, label } }
}
for _, grade in ipairs(grades) do
for _, grade in pairs(grades) do
queries[#queries + 1] = {
query = 'INSERT INTO job_grades (job_name, grade, name, label, salary, skin_male, skin_female) VALUES (?, ?, ?, ?, ?, ?, ?)',
values = { name, grade.grade, grade.name, grade.label, grade.salary, '{}', '{}' }
values = { name, grade.grade, grade.name, grade.label, grade.salary, grade.skin_male and json.encode(grade.skin_male) or '{}', grade.skin_female and json.encode(grade.skin_female) or '{}' }
}
end
@@ -90,5 +90,7 @@ function ESX.CreateJob(name, label, grades)
notify("SUCCESS", currentResourceName, 'Job created successfully: `%s`', name)
TriggerEvent('esx:jobCreated', name, ESX.Jobs[name])
return success
end
+46 -37
View File
@@ -78,57 +78,66 @@ function ESX.OneSync.GetClosestPlayer(source, maxDistance, ignore)
return getNearbyPlayers(source, true, maxDistance, ignore)
end
---@param model number|string
---@param vehicleModel number|string
---@param coords vector3|table
---@param heading number
---@param properties table
---@param vehicleProperties table
---@param cb? fun(netId: number)
---@param vehicleType string?
---@return number? netId
function ESX.OneSync.SpawnVehicle(model, coords, heading, properties, cb)
function ESX.OneSync.SpawnVehicle(vehicleModel, coords, heading, vehicleProperties, cb, vehicleType)
if cb and not ESX.IsFunctionReference(cb) then
error("Invalid callback function")
end
local vehicleModel = joaat(model)
local vehicleProperties = properties
vehicleModel = joaat(vehicleModel)
local promise = not cb and promise.new()
local function resolve(result)
if promise then
promise:resolve(result)
elseif cb then
cb(result)
end
end
local function reject(err)
if promise then
promise:reject(err)
end
error(err)
end
CreateThread(function()
local xPlayer = ESX.OneSync.GetClosestPlayer(coords, 300)
ESX.GetVehicleType(vehicleModel, xPlayer.id, function(vehicleType)
if not vehicleType then
if (promise) then
return promise:reject(("Tried to spawn invalid vehicle - ^5%s^7!"):format(model))
end
error(("Tried to spawn invalid vehicle - ^5%s^7!"):format(model))
local closestPlayer = ESX.OneSync.GetClosestPlayer(coords, 300)
local closestPlayerFound = next(closestPlayer) ~= nil
vehicleType = vehicleType or (closestPlayerFound and ESX.GetVehicleType(vehicleModel, closestPlayer.id) or nil)
if not vehicleType then
return reject("No players found nearby to check vehicle type! Alternatively, you can specify the vehicle type manually.")
end
local createdVehicle = CreateVehicleServerSetter(vehicleModel, vehicleType, coords.x, coords.y, coords.z, heading)
local tries = 0
while not createdVehicle or createdVehicle == 0
or (closestPlayerFound and NetworkGetEntityOwner(createdVehicle) == -1)
or (not closestPlayerFound and not DoesEntityExist(createdVehicle)) do
Wait(200)
tries = tries + 1
if tries > 40 then
return reject(("Could not spawn vehicle - ^5%s^7!"):format(vehicleModel))
end
end
local createdVehicle = CreateVehicleServerSetter(vehicleModel, vehicleType, coords.x, coords.y, coords.z, heading)
local tries = 0
-- luacheck: ignore
SetEntityOrphanMode(createdVehicle, 2)
local networkId = NetworkGetNetworkIdFromEntity(createdVehicle)
Entity(createdVehicle).state:set("VehicleProperties", vehicleProperties, true)
while not createdVehicle or createdVehicle == 0 or NetworkGetEntityOwner(createdVehicle) == -1 do
Wait(200)
tries = tries + 1
if tries > 40 then
if promise then
return promise:reject(("Could not spawn vehicle - ^5%s^7!"):format(model))
end
error(("Could not spawn vehicle - ^5%s^7!"):format(model))
end
end
-- luacheck: ignore
SetEntityOrphanMode(createdVehicle, 2)
local networkId = NetworkGetNetworkIdFromEntity(createdVehicle)
Entity(createdVehicle).state:set("VehicleProperties", vehicleProperties, true)
if promise then
promise:resolve(networkId)
elseif cb then
cb(networkId)
end
end)
resolve(networkId)
end)
if promise then
+12 -5
View File
@@ -1,5 +1,9 @@
Config = {}
local txAdminLocale = GetConvar("txAdmin-locale", "en")
local esxLocale = GetConvar("esx:locale", "invalid")
Config.Locale = (esxLocale ~= "invalid") and esxLocale or (txAdminLocale ~= "custom" and txAdminLocale) or "en"
-- for ox inventory, this will automatically be adjusted, do not change! for other inventories, change to "resource_name"
Config.CustomInventory = false
@@ -35,6 +39,14 @@ Config.AdminGroups = {
["admin"] = true,
}
Config.ValidCharacterSets = { -- Only enable additional charsets if your server is multilingual. By default everything is false.
['el'] = false, -- Greek
['sr'] = false, -- Cyrillic
['he'] = false, -- Hebrew
['ar'] = false, -- Arabic
['zh-cn'] = false -- Chinese, Japanese, Korean
}
Config.EnablePaycheck = true -- enable paycheck
Config.LogPaycheck = false -- Logs paychecks to a nominated Discord channel via webhook (default is false)
Config.EnableSocietyPayouts = false -- pay from the society account that the player is employed at? Requirement: esx_society
@@ -60,8 +72,3 @@ if GetResourceState("ox_inventory") ~= "missing" then
end
Config.EnableDefaultInventory = Config.CustomInventory == false -- Display the default Inventory ( F2 )
local txAdminLocale = GetConvar("txAdmin-locale", "en")
local esxLocale = GetConvar("esx:locale", "invalid")
Config.Locale = (esxLocale ~= "invalid") and esxLocale or (txAdminLocale ~= "custom" and txAdminLocale) or "en"
+75
View File
@@ -210,3 +210,78 @@ function ESX.Await(conditionFunc, errorMessage, timeoutMs)
return false
end
---@param str string
---@param allowDigits boolean? Allow numbers if necessary
---@return boolean
function ESX.IsValidLocaleString(str, allowDigits)
if not ESX.ValidateType(str, 'string') then
return false
end
local locale = string.lower(Config.Locale)
local defaultRanges ={
{0x0041, 0x005A}, -- Basic Latin uppercase
{0x0061, 0x007A}, -- Basic Latin lowercase
{0x0020, 0x0020}, -- Space
{0x002D, 0x002D}, -- Dash
{0x00C0, 0x02AF} -- Latin Extended
}
if allowDigits then
defaultRanges[#defaultRanges + 1] = {0x0030, 0x0039} -- 0-9 Numbers
end
local localeRanges = {
["el"] = { {0x0370, 0x03FF} }, -- Greek
["sr"] ={ {0x0400, 0x04FF} }, -- Cyrillic
["he"] ={ {0x05D0, 0x05EA} }, -- Hebrew letters
["ar"] = {
{0x0620, 0x063F}, -- Arabic
{0x0641, 0x064A},
{0x066E, 0x066F},
{0x0671, 0x06D3},
{0x06D5, 0x06D5},
{0x0750, 0x077F},
{0x08A0, 0x08BD}
},
["zh-cn"] ={ {0x4E00, 0x9FFF} } -- CJK
}
local validRanges = { table.unpack(defaultRanges) }
if localeRanges[locale] then
for i = 1, #localeRanges[locale] do
validRanges[#validRanges + 1] = localeRanges[locale][i]
end
end
if Config.ValidCharacterSets then
for charset, enabled in pairs(Config.ValidCharacterSets) do
if enabled and charset ~= locale and localeRanges[charset] then
for i = 1, #localeRanges[charset] do
validRanges[#validRanges + 1] = localeRanges[charset][i]
end
end
end
end
for _, code in utf8.codes(str) do
local isValid = false
for i = 1, #validRanges do
local range = validRanges[i]
if code >= range[1] and code <= range[2] then
isValid = true
break
end
end
if not isValid then
return false
end
end
return true
end
-2
View File
@@ -8,8 +8,6 @@ AddEventHandler("esx:getSharedObject", function(cb)
if ESX.IsFunctionReference(cb) then
cb(ESX)
end
local invokingResource = GetInvokingResource()
print(("^3[WARNING]^0 Resource ^5%s^0 used the ^5getSharedObject^0 event. This is not the recommended way to import ESX. Visit https://docs.esx-legacy.com/tutorials/tutorials-esx/sharedevent to find out why."):format(invokingResource))
end)
-- backwards compatibility (DO NOT TOUCH !)
+1 -1
View File
@@ -1,4 +1,4 @@
version '1.12.4'
version '1.12.2'
author 'ESX-Framework'
description 'A ESX Stylised theme for the chat resource.'
+1 -1
View File
@@ -4,7 +4,7 @@ game 'gta5'
author 'ESX-Framework & Brayden'
description 'A simplistic context menu for ESX.'
lua54 'yes'
version '1.12.4'
version '1.12.2'
ui_page 'index.html'
+1 -2
View File
@@ -13,8 +13,7 @@ Config.DateFormat = "DD/MM/YYYY"
Config.MaxNameLength = 20 -- Max Name Length.
Config.MinHeight = 120 -- 120 cm lowest height
Config.MaxHeight = 220 -- 220 cm max height.
Config.LowestYear = 1900 -- 112 years old is the oldest you can be.
Config.HighestYear = 2005 -- 18 years old is the youngest you can be.
Config.MaxAge = 100 -- 100 years old is the oldest you can be.
Config.FullCharDelete = true -- Delete all reference to character.
Config.EnableDebugging = ESX.GetConfig().EnableDebug -- prints for debugging :)
+1 -1
View File
@@ -3,7 +3,7 @@ fx_version 'adamant'
game 'gta5'
description 'Allows the player to Pick their characters: Name, Gender, Height and Date-of-birth.'
lua54 'yes'
version '1.12.4'
version '1.12.2'
shared_scripts {
'@es_extended/imports.lua',
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["cs"] = {
return {
["show_registration"] = "zobrazit registracni menu",
["show_active_character"] = "zobrazit aktivni postavy",
["delete_character"] = "smazat svou stavajici postavu a vytvorit novou",
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["da"] = {
return {
["show_active_character"] = "Vis aktiv karakter",
["active_character"] = "Aktiv karakter: %s",
["error_active_character"] = "Der opstod en fejl under indhentning af dine data.",
+2 -2
View File
@@ -1,4 +1,4 @@
Locales["de"] = {
return {
["show_active_character"] = "Aktiven Charakter anzeigen",
["active_character"] = "Aktiver Charakter: %s",
["error_active_character"] = "Beim Abrufen deiner Daten ist ein Fehler aufgetreten",
@@ -35,4 +35,4 @@ Locales["de"] = {
["invalid_dob_format"] = "Ungültiges Format (Geburtstag): Bitte versuche es erneut.",
["invalid_sex_format"] = "Ungültiges Format (Geschlecht): Bitte versuche es erneut.",
["invalid_height_format"] = "Ungültiges Format (Körpergröße): Bitte versuche es erneut.",
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["en"] = {
return {
["show_active_character"] = "Show Active Character",
["active_character"] = "Active Character: %s",
["error_active_character"] = "There was an error obtaining your data.",
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["es"] = {
return {
["show_active_character"] = "Mostrar personaje actual",
["active_character"] = "Personaje actual: %s",
["error_active_character"] = "Se produjo un error al recuperar tu nombre. Por favor contacta con un administrador",
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["fi"] = {
return {
["show_active_character"] = "Näytä nykyinen hahmosi",
["active_character"] = "Nykyinen hahmosi: %s",
["error_active_character"] = "Hahmosi hakemisessa ilmeni ongelma. Ota yhteyttä ylläpitoon.",
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["fr"] = {
return {
["show_active_character"] = "Afficher le personnage actif",
["active_character"] = "Personnage actif: %s",
["error_active_character"] = "Une erreur s'est produite lors de l'obtention de vos données.",
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["he"] = {
return {
["show_active_character"] = "הצג דמות פעילה",
["active_character"] = "דמות פעילה: %s",
["error_active_character"] = "אירעה שגיאה בקבלת הנתונים שלך.",
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["hu"] = {
return {
["show_active_character"] = "Aktív karakterek mutatása",
["active_character"] = "Aktív karakter: %s",
["error_active_character"] = "A név nem megfelelő",
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["it"] = {
return {
["show_active_character"] = "Mostra Personaggio Attivo",
["active_character"] = "Personaggio Attivo: %s",
["error_active_character"] = "Errore nel recuperare i tuoi dati.",
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["nl"] = {
return {
["show_active_character"] = "Actieve karakter laten zien",
["active_character"] = "Actief karakter: %s",
["error_active_character"] = "Er is een probleem opgetreden tijdens het verzamelen van uw data.",
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["pl"] = {
return {
["show_active_character"] = "Pokaż aktywną postać",
["active_character"] = "Aktywna postać: %s",
["error_active_character"] = "Podczas pobierania Twojego imienia wystąpił błąd. Proszę skontaktować się z administratorem.",
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["pt"] = {
return {
["show_active_character"] = "Mostrar personagem ativa",
["active_character"] = "Personagem ativa: %s",
["error_active_character"] = "Houve um erro a obter os teus dados.",
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["sl"] = {
return {
["show_active_character"] = "Prikaži aktivnega lika",
["active_character"] = "Aktivni lik: %s",
["error_active_character"] = "Prišlo je do napake pri pridobivanju podatkov.",
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["sr"] = {
return {
["show_active_character"] = "Prikazi karaktere",
["active_character"] = "Karakteri: %s",
["error_active_character"] = "Imamo problem sa ucitavanjem karaktera.",
+1 -1
View File
@@ -1,4 +1,4 @@
Locales["sv"] = {
return {
["show_active_character"] = "Visa aktiv karaktär",
["active_character"] = "Aktiv karaktär: %s",
["error_active_character"] = "Det blev ett fel med att ta din data.",
+29 -31
View File
@@ -44,31 +44,37 @@ local function saveIdentityToDatabase(identifier, identity)
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
local function checkDOBFormat(str)
str = tostring(str)
if not string.match(str, "(%d%d)/(%d%d)/(%d%d%d%d)") then
---@param year number Year
---@return boolean: true if the year is a leap year, false otherwise
local function isLeapYear(year)
return (year % 4 == 0 and year % 100 ~= 0) or (year % 400 == 0)
end
---@param dob string Date of Birth in the format DD/MM/YYYY
---@return boolean: true if the date is valid, false otherwise
local function checkDOBFormat(dob)
dob = tostring(dob)
local dayStr, monthStr, yearStr = dob:match("^(%d%d?)/(%d%d?)/(%d%d%d%d)$")
if not dayStr or not monthStr or not yearStr then
return false
end
local d, m, y = string.match(str, "(%d+)/(%d+)/(%d+)")
m = tonumber(m)
d = tonumber(d)
y = tonumber(y)
if ((d <= 0) or (d > 31)) or ((m <= 0) or (m > 12)) or ((y <= Config.LowestYear) or (y > Config.HighestYear)) then
local day, month, year = tonumber(dayStr), tonumber(monthStr), tonumber(yearStr)
if not day or not month or not year then
return false
elseif m == 4 or m == 6 or m == 9 or m == 11 then
return d <= 30
elseif m == 2 then
if y % 400 == 0 or (y % 100 ~= 0 and y % 4 == 0) then
return d <= 29
else
return d <= 28
end
else
return d <= 31
end
local currentYear = os.date("*t").year
local minYear = currentYear - Config.MaxAge
local maxYear = currentYear - 18
if year < minYear or year > maxYear then return false end
if month < 1 or month > 12 then return false end
-- Days in each month (starting from January.)
local daysInMonth = { 31, isLeapYear(year) and 29 or 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
return day >= 1 and day <= daysInMonth[month]
end
local function formatDate(str)
@@ -84,16 +90,8 @@ local function formatDate(str)
return date
end
local function checkAlphanumeric(str)
return (string.match(str, "%W"))
end
local function checkForNumbers(str)
return (string.match(str, "%d"))
end
local function checkNameFormat(name)
if not checkAlphanumeric(name) and not checkForNumbers(name) then
if ESX.IsValidLocaleString(name) then
local stringLength = string.len(name)
return stringLength > 0 and stringLength < Config.MaxNameLength
end
@@ -243,7 +241,6 @@ end
ESX.RegisterServerCallback("esx_identity:registerIdentity", function(source, cb, data)
local xPlayer = ESX.GetPlayerFromId(source)
data.dateofbirth = formatDate(data.dateofbirth)
if not checkNameFormat(data.firstname) then
TriggerClientEvent("esx:showNotification", source, TranslateCap("invalid_firstname_format"), "error")
@@ -265,6 +262,7 @@ end
TriggerClientEvent("esx:showNotification", source, TranslateCap("invalid_height_format"), "error")
return cb(false)
end
if xPlayer then
if alreadyRegistered[xPlayer.identifier] then
xPlayer.showNotification(TranslateCap("already_registered"), "error")
@@ -274,7 +272,7 @@ end
playerIdentity[xPlayer.identifier] = {
firstName = formatName(data.firstname),
lastName = formatName(data.lastname),
dateOfBirth = data.dateofbirth,
dateOfBirth = formatDate(data.dateofbirth),
sex = data.sex,
height = data.height,
}
+1 -1
View File
@@ -3,7 +3,7 @@ game 'common'
fx_version 'cerulean'
author 'ESX-Framework'
description 'Allows resources to Run tasks at specific intervals.'
version '1.12.4'
version '1.12.2'
lua54 'yes'
loadscreen 'index.html'
+161 -72
View File
@@ -1,109 +1,198 @@
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@500;600&display=swap");
@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap');
::-webkit-scrollbar {
display: none;
}
.menu {
font-family: "Poppins", sans-serif;
min-width: 350px;
color: #fff;
.menu-container {
position: absolute;
background: rgba(15, 15, 15, 0.0);
text-align: center;
border-radius: 5px;
min-width: 20.8333vw;
height: fit-content;
display: flex;
flex-direction: column;
gap: 0.9259vh;
transform-origin: center center;
}
.menu-container.align-left {
left: 0;
top: 50%;
transform: translateY(-50%) scale(var(--scale, 1));
transform-origin: left center;
}
.menu-container.align-top-left {
left: 4rem;
top: 0.8rem;
transform: scale(var(--scale, 1));
transform-origin: left top;
}
.menu-container.align-top {
left: 50%;
top: 0.8rem;
transform: translateX(-50%) scale(var(--scale, 1));
transform-origin: center top;
}
.menu-container.align-top-right {
right: 3rem;
top: 0.8rem;
transform: scale(var(--scale, 1));
transform-origin: right top;
}
.menu-container.align-right {
right: 0;
top: 50%;
transform: translateY(-50%) scale(var(--scale, 1));
transform-origin: right center;
}
.menu-container.align-bottom-right {
right: 3rem;
bottom: 0.8rem;
transform: scale(var(--scale, 1));
transform-origin: right bottom;
}
.menu-container.align-bottom {
left: 50%;
bottom: 0.8rem;
transform: translateX(-50%) scale(var(--scale, 1));
transform-origin: center bottom;
}
.menu-container.align-bottom-left {
left: 4rem;
bottom: 0.8rem;
transform: scale(var(--scale, 1));
transform-origin: left bottom;
}
.menu-container.align-center {
left: 50%;
top: 50%;
transform: translate(-50%, -50%) scale(var(--scale, 1));
transform-origin: center center;
}
.menu-buttons {
display: flex;
justify-content: center;
gap: .5208vw;
color: #FFF;
font-family: Poppins;
font-size: .8333vw;
font-style: normal;
font-weight: 700;
line-height: normal;
}
.menu-button {
display: flex;
align-items: center;
justify-content: center;
gap: .4167vw;
cursor: pointer;
transition: all 0.3s ease;
}
.backspace-btn, .close-btn {
width: 10.6771vw;
height: 6.0185vh;
border-radius: .2604vw;
background: #161616;
}
.menu-button:hover {
background-color: #252525;
transform: scale(1.02);
}
.menu {
display: flex;
flex-direction: column;
gap: 0.9259vh;
font-family: "Poppins", sans-serif;
color: #fff;
padding: 8px;
background-color: #161616;
border-radius: 4px;
}
.head {
display: block;
overflow: hidden;
padding-bottom: 3px;
min-width: 20.4688vw;
min-height: 6.0185vh;
padding-bottom: 0.2778vh;
text-align: center;
white-space: nowrap;
background: rgba(10, 10, 10, 1);
border-bottom: 2px solid #fb9b04;
border-radius: .2604vw;
background: #FB9B04;
}
.menu .head {
text-align: center;
height: 28px;
color: #ffffff;
display: flex;
justify-content: center;
align-items: center;
color: #252525;
font-family: Poppins;
font-size: 1.25vw;
font-style: normal;
font-weight: 700;
font-size: 20px;
line-height: normal;
height: 100%;
}
.menu .menu-items {
max-height: 450px;
display: flex;
flex-direction: column;
gap: 0.9259vh;
max-height: 41.6667vh;
overflow-y: auto;
font-weight: 550;
}
.menu-items {
margin-bottom: 2px;
margin-bottom: 0.1852vh;
}
.menu .menu-items .menu-item {
display: block;
padding: 7px;
font-size: 13px;
height: 16px;
text-indent: 5px;
background: rgba(30, 30, 30, 0.9);
color: rgb(243, 243, 243);
display: flex;
justify-content: center;
align-items: center;
gap: 1.0833vw;
min-width: 20.4688vw;
min-height: 6.0185vh;
border-radius: .2604vw;
background: #252525;
color: #FFF;
font-family: Poppins;
font-size: .8333vw;
font-style: normal;
font-weight: 700;
line-height: normal;
}
.menu .menu-items .menu-item.selected {
border: 1px solid #fb9c04ec;
background: rgba(15, 15, 15, 0.9);
color: rgba(243, 243, 243);
letter-spacing: 0.2px;
font-weight: 500;
border: 2px solid #FB9B04;
background: #252525;
}
.menu.align-left {
left: 0;
top: 50%;
.menu-item {
display: flex;
align-items: center;
padding: .4167vw 0.9259vh;
}
.menu.align-top-left {
left: 4rem;
top: 0;
.menu-item-icon {
font-size: 1vw;
text-align: center;
}
.menu.align-top {
left: 50%;
top: 0;
.menu-item.selected {
background-color: rgba(255, 255, 255, 0.1);
}
.menu.align-top-right {
right: 3rem;
top: 0;
}
.menu.align-right {
right: 0;
top: 50%;
}
.menu.align-bottom-right {
right: 3rem;
bottom: 0;
}
.menu.align-bottom {
left: 50%;
bottom: 0;
transform: translate(0, -50%);
}
.menu.align-bottom-left {
left: 4rem;
bottom: 0;
}
.menu.align-center {
left: 50%;
top: 35%;
transform: translate(-50%, 50%);
.fas {
color: white;
}
+36 -3
View File
@@ -1,21 +1,31 @@
(function () {
let MenuTpl =
'<div id="menu_{{_namespace}}_{{_name}}" class="menu{{#align}} align-{{align}}{{/align}}">' +
'<div id="menu_{{_namespace}}_{{_name}}" class="menu-container{{#align}} align-{{align}}{{/align}}" style="transform: scale({{scale}});">' +
'<div class="menu">' +
'<div class="head"><span>{{{title}}}</span></div>' +
'<div class="menu-items">' +
"{{#elements}}" +
'<div class="menu-item {{#selected}}selected{{/selected}}">' +
"{{{label}}}{{#isSlider}} : &lt;{{{sliderLabel}}}&gt;{{/isSlider}}" +
'{{#icon}}<div class="menu-item-icon"><i class="fas fa-{{icon}}"></i></div>{{/icon}}' +
'<div class="menu-item-label">{{{label}}}{{#isSlider}} : &lt;{{{sliderLabel}}}&gt;{{/isSlider}}</div>' +
"</div>" +
"{{/elements}}" +
"</div>" +
"</div>" +
'</div>' +
'<div class="menu-buttons">' +
'<div class="menu-button backspace-btn"><i class="fa-solid fa-delete-left"></i> {{locales.backspace}}</div>' +
'<div class="menu-button close-btn"><i class="fa-solid fa-right-to-bracket"></i> {{locales.select}}</div>' +
'</div>' +
"</div>";
window.ESX_MENU = {};
ESX_MENU.ResourceName = "esx_menu_default";
ESX_MENU.opened = {};
ESX_MENU.focus = [];
ESX_MENU.pos = {};
ESX_MENU.locales = {
backspace: "BACK",
select: "SELECT"
};
ESX_MENU.open = function (namespace, name, data) {
if (typeof ESX_MENU.opened[namespace] === "undefined") {
@@ -30,6 +40,12 @@
ESX_MENU.pos[namespace] = {};
}
if (data.locales) {
ESX_MENU.locales = data.locales;
}
data.scale = data.scale || 1;
for (let i = 0; i < data.elements.length; i++) {
if (typeof data.elements[i].type === "undefined") {
data.elements[i].type = "default";
@@ -39,6 +55,7 @@
data._index = ESX_MENU.focus.length;
data._namespace = namespace;
data._name = name;
data.locales = ESX_MENU.locales;
for (let i = 0; i < data.elements.length; i++) {
data.elements[i]._namespace = namespace;
@@ -362,5 +379,21 @@
window.addEventListener("message", (event) => {
onData(event.data);
});
document.addEventListener('click', function(event) {
if (event.target.closest('.backspace-btn')) {
let focused = ESX_MENU.getFocused();
if (typeof focused != "undefined") {
ESX_MENU.cancel(focused.namespace, focused.name);
}
}
if (event.target.closest('.close-btn')) {
let focused = ESX_MENU.getFocused();
if (typeof focused != "undefined") {
ESX_MENU.close(focused.namespace, focused.name);
}
}
});
};
})();
+18 -13
View File
@@ -1,16 +1,21 @@
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="nui://esx_menu_default/html/css/app.css" />
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link href="https://fonts.googleapis.com/css2?family=PT+Sans+Narrow&display=swap" rel="stylesheet" />
</head>
<body>
<div id="menus"></div>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="nui://esx_menu_default/html/css/app.css" />
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link href="https://fonts.googleapis.com/css2?family=PT+Sans+Narrow&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css"
integrity="sha512-Evv84Mr4kqVGRNSgIGL/F/aIDqQb7xQ2vcrdIwxfjThSH8CSR7PBEakCr51Ck+w+/U6swU2Im1vVX0SVk9ABhg=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
</head>
<script src="nui://game/ui/jquery.js" type="text/javascript"></script>
<script src="nui://esx_menu_default/html/js/mustache.min.js" type="text/javascript"></script>
<script src="nui://esx_menu_default/html/js/app.js" type="text/javascript"></script>
</body>
</html>
<body>
<div id="menus"></div>
<script src="nui://game/ui/jquery.js" type="text/javascript"></script>
<script src="nui://esx_menu_default/html/js/mustache.min.js" type="text/javascript"></script>
<script src="nui://esx_menu_default/html/js/app.js" type="text/javascript"></script>
</body>
</html>
+1 -1
View File
@@ -3,7 +3,7 @@ fx_version 'adamant'
game 'gta5'
description 'A basic input dialog for ESX Legacy.'
lua54 'yes'
version '1.12.4'
version '1.12.2'
client_scripts {
'@es_extended/imports.lua',
+1 -1
View File
@@ -3,7 +3,7 @@ fx_version 'adamant'
game 'gta5'
description 'A basic table-based menu system for ESX Legacy.'
lua54 'yes'
version '1.12.4'
version '1.12.2'
client_scripts {
+2 -17
View File
@@ -1,13 +1,3 @@
-- Connection Logic
local function AwaitContext()
while GetResourceState("esx_context") ~= "started" do
Wait(100)
end
return true
end
CreateThread(function()
while not ESX.PlayerLoaded do
@@ -16,13 +6,8 @@ CreateThread(function()
if NetworkIsPlayerActive(ESX.playerId) then
ESX.DisableSpawnManager()
DoScreenFadeOut(0)
local ready = AwaitContext()
if ready then
Multicharacter:SetupCharacters()
break
end
Multicharacter:SetupCharacters()
break
end
end
end)
+25 -139
View File
@@ -1,15 +1,4 @@
Menu = {}
Menu._index = Menu
Menu.currentElements = {}
function Menu:OpenMenu()
ESX.OpenContext("left", self.currentElements, self.onUse, nil, false)
end
function Menu:Close()
self.currentElements = {}
ESX.CloseContext()
end
function Menu:CheckModel(character)
if not character.model and character.skin then
@@ -23,18 +12,6 @@ function Menu:CheckModel(character)
end
end
function Menu:AddCharacters()
for _, v in pairs(Multicharacter.Characters) do
self:CheckModel(v)
local label = ("%s %s"):format(v.firstname, v.lastname)
self.currentElements[#self.currentElements + 1] = { title = label, icon = "fa-regular fa-user", value = v.id}
end
if #self.currentElements - 1 < Multicharacter.slots then
self.currentElements[#self.currentElements + 1] = { title = TranslateCap("create_char"), icon = "fa-solid fa-plus", value = (#self.currentElements + 1), new = true }
end
end
local GetSlot = function()
for i = 1, Multicharacter.slots do
if not Multicharacter.Characters[i] then
@@ -44,7 +21,6 @@ local GetSlot = function()
end
function Menu:NewCharacter()
self:Close()
local slot = GetSlot()
TriggerServerEvent("esx_multicharacter:CharacterChosen", slot, true)
@@ -59,7 +35,7 @@ function Menu:NewCharacter()
end
function Menu:SelectCharacter()
function Menu:InitCharacter()
local Characters = Multicharacter.Characters
local Character = next(Characters)
self:CheckModel(Characters[Character])
@@ -67,125 +43,35 @@ function Menu:SelectCharacter()
if not Multicharacter.spawned then
Multicharacter:SetupCharacter(Character)
end
self.currentElements = {
{
title = TranslateCap("select_char"),
icon = "fa-solid fa-users",
description = TranslateCap("select_char_description"),
unselectable = true
Wait(500)
SendNUIMessage({
action = "ToggleMulticharacter",
data = {
show = true,
Characters = Characters,
CanDelete = Config.CanDelete,
AllowedSlot = Multicharacter.slots,
Locale = Locales[Config.Locale].UI,
}
}
})
self:AddCharacters()
self.onUse = function(_, SelectedCharacter)
if SelectedCharacter.new then
self:NewCharacter()
else
if SelectedCharacter.value ~= Multicharacter.spawned then
Multicharacter:SetupCharacter(SelectedCharacter.value)
local playerPed = PlayerPedId()
SetPedAoBlobRendering(playerPed, true)
ResetEntityAlpha(playerPed)
end
self:CharacterOptions()
end
end
self:OpenMenu()
SetNuiFocus(true, true)
end
function Menu:CharacterOptions()
local currentCharacter = Multicharacter.Characters[Multicharacter.spawned]
local elements = {
{
title = TranslateCap("character", currentCharacter.firstname .. " " .. currentCharacter.lastname),
icon = "fa-regular fa-user",
unselectable = true
},
{
title = TranslateCap("return"),
unselectable = false,
icon = "fa-solid fa-arrow-left",
description = TranslateCap("return_description"),
action = "return"
},
}
if not currentCharacter.disabled then
elements[3] = {
title = TranslateCap("char_play"),
description = TranslateCap("char_play_description"),
icon = "fa-solid fa-play",
action = "play",
}
else
elements[3] = {
title = TranslateCap("char_disabled"),
icon = "fa-solid fa-xmark",
description = TranslateCap("char_disabled_description")
}
end
if Config.CanDelete then
elements[4] = {
title = TranslateCap("char_delete"),
icon = "fa-solid fa-xmark",
description = TranslateCap("char_delete_description"),
action = "delete",
}
end
self.currentElements = elements
self.onUse = function(_, Action)
if Action.action == "play" then
Multicharacter:CloseUI()
self:Close()
TriggerServerEvent("esx_multicharacter:CharacterChosen", Multicharacter.spawned, false)
elseif Action.action == "delete" then
self:ConfirmDeletion()
elseif Action.action == "return" then
self:SelectCharacter()
end
end
self:OpenMenu()
function Menu:SelectCharacter(index)
Multicharacter:SetupCharacter(index)
local playerPed = PlayerPedId()
SetPedAoBlobRendering(playerPed, true)
ResetEntityAlpha(playerPed)
end
function Menu:ConfirmDeletion()
self.currentElements = {
{
title = TranslateCap("char_delete_confirmation"),
icon = "fa-solid fa-users",
description = TranslateCap("char_delete_confirmation_description"),
unselectable = true
},
{
title = TranslateCap("char_delete"),
icon = "fa-solid fa-xmark",
description = TranslateCap("char_delete_yes_description"),
action = "delete",
},
{
title = TranslateCap("return"),
unselectable = false,
icon = "fa-solid fa-arrow-left",
description = TranslateCap("char_delete_no_description"),
action = "return"
},
}
function Menu:PlayCharacter()
Multicharacter:CloseUI()
TriggerServerEvent("esx_multicharacter:CharacterChosen", Multicharacter.spawned, false)
end
self.onUse = function(_, Action)
if Action.action == "delete" then
self:Close()
TriggerServerEvent("esx_multicharacter:DeleteCharacter", Multicharacter.spawned)
Multicharacter.spawned = false
elseif Action.action == "return" then
self:CharacterOptions()
end
end
self:OpenMenu()
function Menu:DeleteCharacter()
TriggerServerEvent("esx_multicharacter:DeleteCharacter", Multicharacter.spawned)
Multicharacter.spawned = false
end
@@ -12,8 +12,8 @@ function Multicharacter:SetupCamera()
local offset = GetOffsetFromEntityInWorldCoords(self.playerPed, 0, 1.7, 0.4)
SetCamCoord(self.cam, offset.x, offset.y, offset.z)
PointCamAtCoord(self.cam, self.spawnCoords.x, self.spawnCoords.y, self.spawnCoords.z + 1.3)
SetCamCoord(self.cam, offset.x + 0.7, offset.y , offset.z)
PointCamAtCoord(self.cam, self.spawnCoords.x + 0.4, self.spawnCoords.y, self.spawnCoords.z + 1.3)
end
function Multicharacter:AwaitFadeIn()
@@ -116,6 +116,10 @@ function Multicharacter:ChangeExistingPed()
local newCharacter = self.Characters[self.tempIndex]
local spawnedCharacter = self.Characters[self.spawned]
if not newCharacter.model then
newCharacter.model = newCharacter.sex == TranslateCap("male") and `mp_m_freemode_01` or `mp_f_freemode_01`
end
if spawnedCharacter and spawnedCharacter.model then
local model = ESX.Streaming.RequestModel(newCharacter.model)
if model then
@@ -123,7 +127,6 @@ function Multicharacter:ChangeExistingPed()
SetModelAsNoLongerNeeded(newCharacter.model)
end
end
TriggerEvent("skinchanger:loadSkin", newCharacter.skin)
end
@@ -135,8 +138,12 @@ end
function Multicharacter:CloseUI()
SendNUIMessage({
action = "closeui",
action = "ToggleMulticharacter",
data = {
show = false
}
})
SetNuiFocus(false, false)
end
function Multicharacter:SetupCharacter(index)
@@ -152,10 +159,6 @@ function Multicharacter:SetupCharacter(index)
self.spawned = index
self.playerPed = PlayerPedId()
self:PrepForUI()
SendNUIMessage({
action = "openui",
character = character,
})
end
function Multicharacter:SetupUI(characters, slots)
@@ -180,7 +183,7 @@ function Multicharacter:SetupUI(characters, slots)
TriggerEvent("esx_identity:showRegisterIdentity")
end)
else
Menu:SelectCharacter()
Menu:InitCharacter()
end
end
@@ -0,0 +1,23 @@
RegisterNuiCallback('SelectCharacter', function (data, cb)
local selectedIndex = tonumber(data.id)
if selectedIndex then
Menu:SelectCharacter(selectedIndex)
end
cb('ok')
end)
RegisterNuiCallback('PlayCharacter', function (data, cb)
Menu:PlayCharacter()
cb('ok')
end)
RegisterNuiCallback('DeleteCharacter', function (data, cb)
Menu:DeleteCharacter()
cb('ok')
end)
RegisterNuiCallback('CreateCharacter', function (data, cb)
Menu:NewCharacter()
cb('ok')
end)
+1 -1
View File
@@ -7,7 +7,7 @@ Config.CanDelete = true
if IsDuplicityVersion() then
-- This is the default number of slots for EVERY player
-- If you want to manage extra slots for specific players you can do it by using '/setslots' and '/remslots' commands
Config.Slots = 4
Config.Slots = 3
--------------------
-- Text to prepend to each character (char#:identifier) - keep it short
+3 -4
View File
@@ -1,9 +1,8 @@
fx_version 'cerulean'
game 'gta5'
author 'ESX-Framework - Linden - KASH'
description 'Allows players to have multiple characters on the same account.'
version '1.12.4'
version '1.12.2'
lua54 'yes'
dependencies { 'es_extended', 'esx_context', 'esx_identity', 'esx_skin' }
@@ -21,6 +20,6 @@ client_scripts {
'client/*.lua'
}
ui_page { 'html/ui.html' }
ui_page 'web/build/index.html'
files { 'html/ui.html', 'html/css/main.css', 'html/js/app.js', 'html/locales/*.js' }
files { 'web/build/index.html', 'web/build/**/*.*'}
@@ -1,76 +0,0 @@
@import url("https://fonts.googleapis.com/css2?family=Raleway:wght@300;600&display=swap");
@import url("https://fonts.googleapis.com/css2?family=Oswald&display=swap");
* {
margin: 0;
padding: 0;
user-select: none;
color: rgb(255, 255, 255);
border-radius: 15px;
font-weight: 300;
font-size: 1.6vh;
font-family: Calibri, "Helvetica", san-serif;
}
html {
overflow: hidden;
}
p {
margin: 0 !important;
}
body {
background: transparent;
}
.main-container {
display: none;
position: absolute;
top: 50%;
right: 150;
transform: translate(0, -50%);
border-radius: 15px;
background: rgba(15, 15, 15, 0.9);
}
.header {
font-family: "Oswald", sans-serif;
position: absolute;
background: rgba(10, 10, 10, 0.9);
border-radius: 15px 15px 0px 0px;
height: 10%;
width: 100%;
left: 50%;
text-align: center;
transform: translate(-50%);
font-weight: 700;
padding-bottom: 5px;
font-size: 1.6rem;
}
.footer {
position: absolute;
font-size: 0rem;
}
.character-box {
display: flex;
right: 0;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
line-height: 1.4rem;
height: calc(30rem);
width: 17rem;
border: 1px rgba(10, 10, 10, 0.7) solid;
box-shadow: 2px 1px 9px 3px rgba(10, 10, 10, 0.7);
}
h1 {
font-family: "Oswald", sans-serif;
font-size: 22px;
padding-top: 1.3rem;
display: block;
font-weight: 0;
}
-66
View File
@@ -1,66 +0,0 @@
var money = Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
minimumFractionDigits: 0,
});
(() => {
Kashacter = {};
Kashacter.ShowUI = function (data) {
$("body").css({ display: "block" });
$(".main-container").css({ display: "block" });
$("[data-charid=1]")
.html(
'<div class="character-info"><p class="character-info-name"><h1>' +
`${translate.name} ` +
"</h1><span>" +
data.firstname +
" " +
data.lastname +
'</span></p><p class="character-info-work"><h1>' +
`${translate.job} ` +
"</h1><span>" +
data.job +
" " +
data.job_grade +
'</span></p><p class="character-info-money"><h1>' +
`${translate.money} ` +
"</h1><span> " +
money.format(data.money) +
'</span></p><p class="character-info-bank"><h1>' +
`${translate.bank} ` +
"</h1><span> " +
money.format(data.bank) +
'</span></p> <p class="character-info-dateofbirth"><h1>' +
`${translate.dob} ` +
"</h1><span>" +
data.dateofbirth +
'</span></p> <p class="character-info-gender"><h1>' +
`${translate.gender} ` +
"</h1><span>" +
data.sex +
"</span></p></div>"
)
.attr("data-ischar", "true");
};
Kashacter.CloseUI = function () {
$("body").css({ display: "none" });
$(".main-container").css({ display: "none" });
$("[data-charid=1]").html('<h3 class="character-fullname"></h3><div class="character-info"><p class="character-info-new"></p></div>');
};
window.onload = function (e) {
window.addEventListener("message", function (event) {
switch (event.data.action) {
case "openui":
Kashacter.ShowUI(event.data.character);
break;
case "closeui":
Kashacter.CloseUI();
break;
}
});
};
})();
@@ -1,8 +0,0 @@
const translate = new Object();
translate.name = "Jméno";
translate.job = "Práce";
translate.bank = "Banka";
translate.money = "Peníze";
translate.gender = "Pohlaví";
translate.dob = "Datum narození";
@@ -1,8 +0,0 @@
const translate = new Object();
translate.name = "Name";
translate.job = "Beruf";
translate.bank = "Bankguthaben";
translate.money = "Bargeld";
translate.gender = "Geschlecht";
translate.dob = "Geburtsdatum";
@@ -1,8 +0,0 @@
const translate = new Object();
translate.name = "Name";
translate.job = "Job";
translate.bank = "Bank";
translate.money = "Cash";
translate.gender = "Gender";
translate.dob = "Date of birth";
@@ -1,8 +0,0 @@
const translate = new Object();
translate.name = "Nombre";
translate.job = "Trabajo";
translate.bank = "Banco";
translate.money = "Dinero";
translate.gender = "Género";
translate.dob = "Fecha de nacimiento";
@@ -1,8 +0,0 @@
const translate = new Object();
translate.name = "Nimi";
translate.job = "Työ";
translate.bank = "Pankki";
translate.money = "Käteinen";
translate.gender = "Sukupuoli";
translate.dob = "Syntymäaika";
@@ -1,8 +0,0 @@
const translate = new Object();
translate.name = "Nom";
translate.job = "Métier";
translate.bank = "Banque";
translate.money = "Argent";
translate.gender = "Sexe";
translate.dob = "Date de naissance";
@@ -1,8 +0,0 @@
const translate = new Object();
translate.name = "Név";
translate.job = "Munka";
translate.bank = "Bank";
translate.money = "Készpénz";
translate.gender = "Nem";
translate.dob = "Születési idő";
@@ -1,8 +0,0 @@
const translate = new Object();
translate.name = "Nome";
translate.job = "Lavoro";
translate.bank = "Banca";
translate.money = "Contanti";
translate.gender = "Genere";
translate.dob = "Data di nascita";
@@ -1,8 +0,0 @@
const translate = new Object();
translate.name = "Naam";
translate.job = "Job";
translate.bank = "Bank";
translate.money = "Cash";
translate.gender = "Gender";
translate.dob = "Geboortedatum";
@@ -1,8 +0,0 @@
const translate = new Object();
translate.name = "imię";
translate.job = "Zajęcie";
translate.bank = "Bank";
translate.money = "Gotówka";
translate.gender = "Seks";
translate.dob = "Data urodzenia";
@@ -1,8 +0,0 @@
const translate = new Object();
translate.name = "Nome";
translate.job = "Trabalho";
translate.bank = "Banco";
translate.money = "Dinheiro";
translate.gender = "Género";
translate.dob = "Data de Nascimento";
@@ -1,8 +0,0 @@
const translate = new Object();
translate.name = "Ime";
translate.job = "Posao";
translate.bank = "Banka";
translate.money = "Novac";
translate.gender = "Pol";
translate.dob = "Datum rodjenja";
@@ -1,8 +0,0 @@
const translate = new Object();
translate.name = "Namn";
translate.job = "Jobb";
translate.bank = "Bank";
translate.money = "Kontanter";
translate.gender = "Kön";
translate.dob = "Födelsedatum";
@@ -1,8 +0,0 @@
const translate = new Object();
translate.name = "我的姓名";
translate.job = "我的职业";
translate.bank = "银行存款";
translate.money = "手持现金";
translate.gender = "我的性别";
translate.dob = "出生日期";
-22
View File
@@ -1,22 +0,0 @@
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<!-- Custom CSS -->
<link rel="stylesheet" type="text/css" href="css/main.css" />
<!-- Locales -->
<script src="locales/en.js"></script>
</head>
<body style="display: none">
<div class="main-container">
<div class="header">Character Info</div>
<div class="character-box" data-charid="1">
<h3 class="character-fullname"></h3>
<div class="character-info"></div>
</div>
<div class="footer">Multicharacter</div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script src="js/app.js" type="text/javascript"></script>
</body>
</html>
+18 -24
View File
@@ -1,28 +1,22 @@
Locales["cs"] = {
["male"] = "Muž",
["female"] = "Žena",
["select_char"] = "Zvolit Postavu",
["select_char_description"] = "Zvol si postavu za kterou budeš hrát.",
["create_char"] = "Vytvořit Novou Postavu",
["char_play"] = "Hrát za postavu",
["char_play_description"] = "Pokračovat do města.",
["char_disabled"] = "Tato postava je zakázána!",
["char_disabled_description"] = "Tuto postavu nemůžeš používat.",
["char_delete"] = "Vymazat postavu",
["char_delete_description"] = "Na vždy smazat tuto postavu.",
["character"] = "Postava: %s",
["return"] = "Zpět",
["return_description"] = "Vrátit se na vybírání postav.",
["command_setslots"] = "Nastavit sloty pro hráče v multicharacteru",
["command_remslots"] = "Odebrat sloty pro hráče v multicharacteru",
["command_enablechar"] = "Povolit zvolený slot hráči",
["command_disablechar"] = "Zakázat zvolený slot pro hrače",
["command_charslot"] = "Číslo slotu",
["command_identifier"] = "Identifier hráče",
["command_slots"] = "# ze slotu",
["slotsadd"] = "Nastavil si slot %s hráči %s",
["slotsrem"] = "Odebral si slot %s",
["charenabled"] = "Povolil si postavu #%s z %s",
["chardisabled"] = "Zakázal si postavu #%s z %s",
["charnotfound"] = "Postava #%s z %s nebyla nalezena/neexistuje",
["command_setslots"] = "Nastavit počet multicharakterových slotů hráče",
["command_remslots"] = "Odebrat počet multicharakterových slotů hráče",
["command_enablechar"] = "Povolit danou postavu hráče",
["command_disablechar"] = "Zakázat danou postavu hráče",
["command_charslot"] = "Číslo slotu postavy",
["command_identifier"] = "Identifikátor hráče",
["command_slots"] = "Počet slotů",
["slotsadd"] = "Nastavil jsi %s slotů pro %s",
["slotsrem"] = "Odebral jsi sloty pro %s",
["charenabled"] = "Povolil jsi postavu #%s hráče %s",
["chardisabled"] = "Zakázal jsi postavu #%s hráče %s",
["charnotfound"] = "Postava #%s hráče %s neexistuje",
UI = {
["title"] = "VÝBĚR POSTAVY",
["char_info_title"] = "Informace o postavě",
["play"] = "HRÁT",
}
}
+18 -28
View File
@@ -1,32 +1,22 @@
Locales["da"] = {
["male"] = "Mand",
["female"] = "Kvinde",
["select_char"] = "Vælg karakter",
["select_char_description"] = "Vælg en karakter at spille som.",
["create_char"] = "Ny Karakter",
["char_play"] = "Spil",
["char_play_description"] = "Fortsæt ind i byen.",
["char_disabled"] = "Deaktiveret",
["char_disabled_description"] = "Denne karakter er ubrugelig.",
["char_delete"] = "Slet",
["char_delete_description"] = "Fjern denne karakter permanent.",
["char_delete_confirmation"] = "Slet bekræftelse",
["char_delete_confirmation_description"] = "Er du sikker på at fjerne det valgte karakter?",
["char_delete_yes_description"] = "Ja, jeg er sikker på at fjerne det valgte karakter",
["char_delete_no_description"] = "Nej, vend tilbage til karakter-indstillinger",
["character"] = "Karakter: %s",
["return"] = "Tilbage",
["return_description"] = "Vend tilbage til valg af karaktere.",
["command_setslots"] = "Indstil flerkarakters slotsnummer for en spiller",
["command_remslots"] = "Fjern flerkarakters slotsnummer for en spiller",
["command_enablechar"] = "Aktiver en valgt karakter af en spiller",
["command_disablechar"] = "Deaktiver en valgt karakter af en spiller",
["command_charslot"] = "Karakterens plads nummer",
["command_identifier"] = "Spiller identifikator",
["command_slots"] = "# af slots",
["slotsadd"] = "Du indstillerde %s slots til %s",
["slotsrem"] = "Du fjernede slots til %s",
["charenabled"] = "Du aktiverede karakter #%s af %s",
["chardisabled"] = "Du deaktiverede tegn #%s af %s",
["charnotfound"] = "Karakter #%s af %s eksisterer ikke",
["command_setslots"] = "Indstil antal multikarakter-slots for en spiller",
["command_remslots"] = "Fjern antal multikarakter-slots for en spiller",
["command_enablechar"] = "Aktivér en given karakter for en spiller",
["command_disablechar"] = "Deaktivér en given karakter for en spiller",
["command_charslot"] = "Karakterens slotnummer",
["command_identifier"] = "Spillerens identifikator",
["command_slots"] = "Antal slots",
["slotsadd"] = "Du satte %s slots til %s",
["slotsrem"] = "Du fjernede slots fra %s",
["charenabled"] = "Du aktiverede karakter #%s for %s",
["chardisabled"] = "Du deaktiverede karakter #%s for %s",
["charnotfound"] = "Karakter #%s for %s findes ikke",
UI = {
["title"] = "KARAKTERVALG",
["char_info_title"] = "Karakterinformation",
["play"] = "SPIL",
}
}
+21 -31
View File
@@ -1,32 +1,22 @@
Locales["de"] = {
["male"] = "Männlich",
["female"] = "Weiblich",
["select_char"] = "Charakter auswählen",
["select_char_description"] = "Wähle einen Charakter aus, mit den du spielen willst.",
["create_char"] = "Neuer Charakter",
["char_play"] = "Spielen",
["char_play_description"] = "Weiter in die Stadt.",
["char_disabled"] = "Deaktiviert",
["char_disabled_description"] = "Dieser Charakter ist deaktiviert.",
["char_delete"] = "Löschen",
["char_delete_description"] = "Dieser Charakter wird dauerhaft entfernt.",
["char_delete_confirmation"] = "Bestätigung zur Entfernung deines Charakters.",
["char_delete_confirmation_description"] = "Bist du sicher, dass du den ausgewählten Charakter entfernen willst?",
["char_delete_yes_description"] = "Ja, ich bin sicher, dass ich den ausgewählten Charakter lösche",
["char_delete_no_description"] = "Nein, zurück zu den Charakteroptionen",
["character"] = " Charakter: %s",
["return"] = "Zurück",
["return_description"] = "Zur Charakterauswahl zurückkehren.",
["command_setslots"] = "Anzahl der Charakter-Slots eines Spielers festlegen",
["command_remslots"] = "Die Anzahl der Charakter-Slots eines Spielers entfernen",
["command_enablechar"] = "Aktiviere einen bestimmten Charakter eines Spielers",
["command_disablechar"] = "Deaktiviere einen bestimmten Charakter eines Spielers",
["command_charslot"] = "Slotnummer des Charakters",
["command_identifier"] = "Spieler R* ID",
["command_slots"] = "Anzahl von Charakter-Slots",
["slotsadd"] = "Du hast %s Charakter-Slots auf %s gesetzt",
["slotsrem"] = "Du hast &s Charakter-Slots auf %s entfernt",
["charenabled"] = "Du hast den Charakter #%s von %s aktiviert",
["chardisabled"] = "Du hast den Charakter #%s von %s deaktiviert",
["charnotfound"] = "Charakter #%s von %s existiert nicht",
}
["male"] = "Männlich",
["female"] = "Weiblich",
["command_setslots"] = "Anzahl der Mehrcharakter-Slots eines Spielers festlegen",
["command_remslots"] = "Anzahl der Mehrcharakter-Slots eines Spielers entfernen",
["command_enablechar"] = "Einen bestimmten Charakter eines Spielers aktivieren",
["command_disablechar"] = "Einen bestimmten Charakter eines Spielers deaktivieren",
["command_charslot"] = "Slot-Nummer des Charakters",
["command_identifier"] = "Spielerkennung",
["command_slots"] = "Anzahl der Slots",
["slotsadd"] = "Du hast %s Slots für %s festgelegt",
["slotsrem"] = "Du hast Slots von %s entfernt",
["charenabled"] = "Du hast Charakter #%s von %s aktiviert",
["chardisabled"] = "Du hast Charakter #%s von %s deaktiviert",
["charnotfound"] = "Charakter #%s von %s existiert nicht",
UI = {
["title"] = "CHARAKTERAUSWAHL",
["char_info_title"] = "Charakterinformation",
["play"] = "SPIELEN",
}
}
+6 -16
View File
@@ -1,22 +1,6 @@
Locales["en"] = {
["male"] = "Male",
["female"] = "Female",
["select_char"] = "Select Character",
["select_char_description"] = "Select a character to play as.",
["create_char"] = "New Character",
["char_play"] = "Play",
["char_play_description"] = "Continue Into The City.",
["char_disabled"] = "Disabled",
["char_disabled_description"] = "This Character Is Unusable.",
["char_delete"] = "Delete",
["char_delete_description"] = "Permanently Remove This Character.",
["char_delete_confirmation"] = "Delete Confirmation",
["char_delete_confirmation_description"] = "Are you sure removing selected character?",
["char_delete_yes_description"] = "Yes, I am sure removing selected character",
["char_delete_no_description"] = "No, return to character options",
["character"] = "Character: %s",
["return"] = "Return",
["return_description"] = "Return To Character Selection.",
["command_setslots"] = "Set multicharacter slots number of a player",
["command_remslots"] = "Remove multicharacter slots number of a player",
["command_enablechar"] = "Enable a given character of a player",
@@ -29,4 +13,10 @@ Locales["en"] = {
["charenabled"] = "You enabled character #%s of %s",
["chardisabled"] = "You disabled character #%s of %s",
["charnotfound"] = "Character #%s of %s doesn't exist",
UI = {
["title"] = "CHARACTER SELECTION",
["char_info_title"] = "Character Info",
["play"] = "PLAY",
}
}
+19 -25
View File
@@ -1,28 +1,22 @@
Locales["es"] = {
["male"] = "Masculino",
["female"] = "Femenino",
["select_char"] = "Seleccionar personaje",
["select_char_description"] = "Selecciona un personaje para jugar.",
["create_char"] = "Crear nuevo personaje",
["char_play"] = "Seleccionar personaje",
["char_play_description"] = "Ingresar a la ciudad.",
["char_disabled"] = "Este personaje está deshabilitado",
["char_disabled_description"] = "Este personaje no se encuentra disponible.",
["char_delete"] = "Borrar el personaje seleccionado",
["char_delete_description"] = "Eliminar este personaje.",
["character"] = "Personaje: %s",
["return"] = "Volver",
["return_description"] = "Volver a la selección de personajes.",
["command_setslots"] = "Establecer el numero de slots de un jugador",
["command_remslots"] = "Elimina slots de un jugador.",
["command_enablechar"] = "Activar el personaje de un jugador",
["command_disablechar"] = "Deshabilitar personaje al jugador.",
["command_charslot"] = "Número de slot del personaje",
["male"] = "Hombre",
["female"] = "Mujer",
["command_setslots"] = "Establecer número de ranuras multicaracter para un jugador",
["command_remslots"] = "Eliminar número de ranuras multicaracter para un jugador",
["command_enablechar"] = "Habilitar un personaje específico de un jugador",
["command_disablechar"] = "Deshabilitar un personaje específico de un jugador",
["command_charslot"] = "Número de ranura del personaje",
["command_identifier"] = "Identificador del jugador",
["command_slots"] = "Nº de slots",
["slotsadd"] = "Has establecido los slots de %s a %s",
["slotsrem"] = "Has eliminado un slot a %s",
["charenabled"] = "Has habilitado el personaje %s de %s",
["chardisabled"] = "Has deshabilitado el personaje %s de %s",
["charnotfound"] = "Personaje %s de %s no existe",
["command_slots"] = "Número de ranuras",
["slotsadd"] = "Has establecido %s ranuras para %s",
["slotsrem"] = "Has eliminado ranuras para %s",
["charenabled"] = "Has habilitado el personaje #%s de %s",
["chardisabled"] = "Has deshabilitado el personaje #%s de %s",
["charnotfound"] = "El personaje #%s de %s no existe",
UI = {
["title"] = "SELECCIÓN DE PERSONAJE",
["char_info_title"] = "Información del personaje",
["play"] = "JUGAR",
}
}
+17 -28
View File
@@ -1,33 +1,22 @@
Locales["fi"] = {
["male"] = "Mies",
["female"] = "Nainen",
["select_char"] = "Valitse hahmo",
["select_char_description"] = "Valitse hahmo, jolla haluat pelata.",
["create_char"] = "Uusi hahmo",
["char_play"] = "Pelaa",
["char_play_description"] = "Jatka kaupunkiin.",
["char_disabled"] = "Ei käytössä",
["char_disabled_description"] = "Tämä hahmo on käyttökelvoton.",
["char_delete"] = "Poista",
["char_delete_description"] = "Poista tämä hahmo pysyvästi.",
["char_delete_confirmation"] = "Vahvista poistaminen.",
["char_delete_confirmation_description"] = "Oletko varma, että poistat valitun hahmon?",
["char_delete_yes_description"] = "Kyllä, olen varma, että poistan valitun hahmon",
["char_delete_no_description"] = "Ei, Palaa hahmojen valintaan",
["character"] = "Hahmo: %s",
["return"] = "Takaisin",
["return_description"] = "Palaa hahmojen valintaan.",
["command_setslots"] = "Määritä pelaajan multicharacter paikkojen määrä",
["command_remslots"] = "Vähennä pelaajan multicharacter paikkojen määrää",
["command_enablechar"] = "Muuta pelaajan tietty hahmo käyttöön",
["command_disablechar"] = "Muuta pelaajan tietty hahmo pois käytöstä",
["command_charslot"] = "Hahmon paikan numero",
["command_setslots"] = "Aseta pelaajalle monihahmoslottien määrä",
["command_remslots"] = "Poista pelaajalta monihahmoslotteja",
["command_enablechar"] = "Ota käyttöön pelaajan tietty hahmo",
["command_disablechar"] = "Poista käytöstä pelaajan tietty hahmo",
["command_charslot"] = "Hahmon slottinumero",
["command_identifier"] = "Pelaajan tunniste",
["command_slots"] = "# paikoista",
["slotsadd"] = "Lisäsit %s paikkaa kohteeseen %s",
["slotsedit"] = "Olet määrittänyt %s kohteeseen %s",
["slotsrem"] = "Poistit paikat kohteesta %s",
["charenabled"] = "Otit käyttöön hahmon #%s / %s",
["chardisabled"] = "Poistit hahmon #%s / %s käytöstä",
["charnotfound"] = "Hahmoa #%s / %s ei ole olemassa",
["command_slots"] = "Slottien määrä",
["slotsadd"] = "Asetit %s slottia pelaajalle %s",
["slotsrem"] = "Poistit slottien määrän pelaajalta %s",
["charenabled"] = "Otat käyttöön hahmon #%s pelaajalta %s",
["chardisabled"] = "Poistit käytöstä hahmon #%s pelaajalta %s",
["charnotfound"] = "Hahmo #%s pelaajalta %s ei ole olemassa",
UI = {
["title"] = "HAHMON VALINTA",
["char_info_title"] = "Hahmon tiedot",
["play"] = "PELAA",
}
}
+15 -25
View File
@@ -1,32 +1,22 @@
Locales["fr"] = {
["male"] = "Homme",
["female"] = "Femme",
["select_char"] = "Sélectionnez un personnage",
["select_char_description"] = "Sélectionnez un personnage avec lequel jouer.",
["create_char"] = "Créer un nouveau personnage",
["char_play"] = "Jouer ce personnage",
["char_play_description"] = "Continuez dans la ville.",
["char_disabled"] = "Ce personnage est désactivé",
["char_disabled_description"] = "Ce personnage est inutilisable.",
["char_delete"] = "Supprimer ce personnage",
["char_delete_description"] = "Supprimer définitivement ce personnage.",
["char_delete_confirmation"] = "Confirmation de suppression",
["char_delete_confirmation_description"] = "Êtes-vous sûr de vouloir supprimer ce personnage?",
["char_delete_yes_description"] = "Oui, je suis sur de vouloir supprimer ce personnage",
["char_delete_no_description"] = "Non, retourner aux options de personnages",
["character"] = "Personnage: %s",
["return"] = "Retour",
["return_description"] = "Retourner à la sélection de personnage.",
["command_setslots"] = "Définir le numéro de créneau multi-caractères d'un joueur",
["command_remslots"] = "Suppression du numéro de créneau multi-caractères d'un joueur",
["command_enablechar"] = "Activer un personnage donné d'un joueur",
["command_disablechar"] = "Désactiver un personnage donné d'un joueur",
["command_charslot"] = "Numéro d'emplacement du caractère",
["command_setslots"] = "Définir le nombre d'emplacements multicaractères d'un joueur",
["command_remslots"] = "Retirer le nombre d'emplacements multicaractères d'un joueur",
["command_enablechar"] = "Activer un personnage spécifique d'un joueur",
["command_disablechar"] = "Désactiver un personnage spécifique d'un joueur",
["command_charslot"] = "Numéro d'emplacement du personnage",
["command_identifier"] = "Identifiant du joueur",
["command_slots"] = "# de slots",
["slotsadd"] = "Vous avez défini %s slots à %s",
["slotsrem"] = "Vous avez suprimé les slots à %s",
["command_slots"] = "Nombre d'emplacements",
["slotsadd"] = "Vous avez défini %s emplacements pour %s",
["slotsrem"] = "Vous avez retiré des emplacements pour %s",
["charenabled"] = "Vous avez activé le personnage #%s de %s",
["chardisabled"] = "Vous avez désactivé le personnage #%s de %s",
["charnotfound"] = "Le personnage #%s de %s n'éxiste",
["charnotfound"] = "Le personnage #%s de %s n'existe pas",
UI = {
["title"] = "SÉLECTION DE PERSONNAGE",
["char_info_title"] = "Infos du personnage",
["play"] = "JOUER",
}
}
+18 -28
View File
@@ -1,32 +1,22 @@
Locales["gr"] = {
["male"] = "Άνδρας",
["female"] = "Γυναίκα",
["select_char"] = "Επιλογή Χαρακτήρα",
["select_char_description"] = "Επιλέξτε ένα χαρακτήρα για να παίξετε.",
["create_char"] = "Νέος Χαρακτήρας",
["char_play"] = "Παίξτε",
["char_play_description"] = "Συνέχεια στην πόλη.",
["char_disabled"] = "Απενεργοποιημένος",
["char_disabled_description"] = "Αυτός ο χαρακτήρας δεν είναι χρησιμοποιήσιμος.",
["char_delete"] = "Διαγραφή",
["char_delete_description"] = "Διαγράψτε οριστικά αυτόν τον χαρακτήρα.",
["char_delete_confirmation"] = "Επιβεβαίωση Διαγραφής",
["char_delete_confirmation_description"] = "Είστε σίγουρος ότι θέλετε να διαγράψετε τον επιλεγμένο χαρακτήρα;",
["char_delete_yes_description"] = "Ναι, είμαι σίγουρος ότι θέλω να διαγράψω τον επιλεγμένο χαρακτήρα",
["char_delete_no_description"] = "Όχι, επιστροφή στις επιλογές χαρακτήρα",
["character"] = "Χαρακτήρας: %s",
["return"] = "Επιστροφή",
["return_description"] = "Επιστροφή στην επιλογή χαρακτήρα.",
["command_setslots"] = "Ορίστε τον αριθμό των slot πολλαπλών χαρακτήρων ενός παίκτη",
["command_remslots"] = "Αφαιρέστε τον αριθμό των slot πολλαπλών χαρακτήρων ενός παίκτη",
["command_enablechar"] = "Ενεργοποιήστε έναν συγκεκριμένο χαρακτήρα ενός παίκτη",
["command_disablechar"] = "Απενεργοποιήστε έναν συγκεκριμένο χαρακτήρα ενός παίκτη",
["command_charslot"] = "Αριθμός υποδιαίρεσης του χαρακτήρα",
["command_identifier"] = "Ταυτότητα παίκτη",
["command_slots"] = "Αριθμός slot",
["slotsadd"] = "Ορίσατε %s slot σε %s",
["slotsrem"] = "Αφαιρέσατε slot από τον %s",
["charenabled"] = "Ενεργοποιήσατε τον χαρακτήρα #%s του %s",
["chardisabled"] = "Απενεργοποιήσατε τον χαρακτήρα #%s του %s",
["charnotfound"] = "Ο χαρακτήρας #%s του %s δεν υπάρχει",
["command_setslots"] = "Ορισμός αριθμού multicharacter θέσεων για έναν παίκτη",
["command_remslots"] = "Αφαίρεση αριθμού multicharacter θέσεων από έναν παίκτη",
["command_enablechar"] = "Ενεργοποίηση συγκεκριμένου χαρακτήρα ενός παίκτη",
["command_disablechar"] = "Απενεργοποίηση συγκεκριμένου χαρακτήρα ενός παίκτη",
["command_charslot"] = "Αριθμός θέσης χαρακτήρα",
["command_identifier"] = "Αναγνωριστικό παίκτη",
["command_slots"] = "Αριθμός θέσεων",
["slotsadd"] = "Ορίσατε %s θέσεις για τον/την %s",
["slotsrem"] = "Αφαιρέσατε θέσεις από τον/την %s",
["charenabled"] = "Ενεργοποιήσατε τον χαρακτήρα #%s του/της %s",
["chardisabled"] = "Απενεργοποιήσατε τον χαρακτήρα #%s του/της %s",
["charnotfound"] = "Ο χαρακτήρας #%s του/της %s δεν υπάρχει",
UI = {
["title"] = "ΕΠΙΛΟΓΗ ΧΑΡΑΚΤΗΡΑ",
["char_info_title"] = "Πληροφορίες Χαρακτήρα",
["play"] = "ΠΑΙΞΕ",
}
}
+15 -25
View File
@@ -1,32 +1,22 @@
Locales["he"] = {
["male"] = "זכר",
["female"] = "נקבה",
["select_char"] = "בחר דמות",
["select_char_description"] = "בחר דמות לשחק.",
["create_char"] = "דמות חדשה",
["char_play"] = "שחק",
["char_play_description"] = "המשך לעיר.",
["char_disabled"] = "מושבת",
["char_disabled_description"] = "דמות זו לא ניתן לשימוש.",
["char_delete"] = "מחק",
["char_delete_description"] = "הסר את הדמות לצמיתות.",
["char_delete_confirmation"] = "אישור מחיקה",
["char_delete_confirmation_description"] = "האם אתה בטוח שאתה מסיר את הדמות שנבחרה?",
["char_delete_yes_description"] = "כן, אני בטוח שאני מסיר את הדמות שנבחרה",
["char_delete_no_description"] = "לא, חזור לאפשרויות הדמות",
["character"] = "דמות: %s",
["return"] = "חזור",
["return_description"] = "חזור לבחירת הדמות.",
["command_setslots"] = "הגדר מספר מקומות לדמות של שחקן",
["command_remslots"] = "הסר מספר מקומות לדמות של שחקן",
["command_setslots"] = "הגדר מספר חריצי דמויות מרובות לשחקן",
["command_remslots"] = "הסר מספר חריצי דמויות מרובות משחקן",
["command_enablechar"] = "אפשר דמות מסוימת של שחקן",
["command_disablechar"] = "השבת דמות מסוימת של שחקן",
["command_charslot"] = "מספר מקום של הדמות",
["command_disablechar"] = "נטרל דמות מסוימת של שחקן",
["command_charslot"] = "מספר חריץ הדמות",
["command_identifier"] = "מזהה שחקן",
["command_slots"] = "# של מקומות",
["slotsadd"] = "הגדרת %s מקומות ל- %s",
["slotsrem"] = "הסרת מקומות ל- %s",
["charenabled"] = "אפשרת את הדמות #%s של %s",
["chardisabled"] = "השבתת את הדמות #%s של %s",
["command_slots"] = "מספר חריצים",
["slotsadd"] = "הגדרת %s חריצים עבור %s",
["slotsrem"] = "הסרת חריצים מ-%s",
["charenabled"] = "איפשרת את הדמות #%s של %s",
["chardisabled"] = "נטרלת את הדמות #%s של %s",
["charnotfound"] = "הדמות #%s של %s לא קיימת",
UI = {
["title"] = "בחירת דמות",
["char_info_title"] = "פרטי דמות",
["play"] = "שחק",
}
}
+18 -28
View File
@@ -1,32 +1,22 @@
Locales["hu"] = {
["male"] = "Férfi",
["female"] = "",
["select_char"] = "Karakter kiválasztása",
["select_char_description"] = "Karakter kiválasztása a játékhoz.",
["create_char"] = "Új karakter létrehozása",
["char_play"] = "Karakter kiválasztása",
["char_play_description"] = "Visszatérés a városba.",
["char_disabled"] = "Karakter le van tiltva",
["char_disabled_description"] = "Ez a karakter nem használható.",
["char_delete"] = "Karakter törlése",
["char_delete_description"] = "Karakter végleges törlése.",
["char_delete_confirmation"] = "Törlés megerősítés",
["char_delete_confirmation_description"] = "Biztosan törölni szeretnéd a kiválasztott karaktert?",
["char_delete_yes_description"] = "Igen, törölni szeretném",
["char_delete_no_description"] = "Nem, vissza a karakter opciókhoz",
["character"] = "Karakter: %s",
["return"] = "Vissza",
["return_description"] = "Vissza a karakter választáshoz.",
["command_setslots"] = "Játékos karakter slotok számának beállítása",
["command_remslots"] = "Játékos karakter slotok számának eltávolítása",
["command_enablechar"] = "Játékos karakterének engedélyezése",
["command_disablechar"] = "Játékos karakterének tiltása",
["command_charslot"] = "Karakter slotok számának beállítása",
["command_identifier"] = "Játékos identifier",
["command_slots"] = "# slotok",
["slotsadd"] = "Beállítottad %s slotokat, neki %s",
["slotsrem"] = "Eltávolítottad a következő slotokat: %s",
["charenabled"] = "Karakter engedélyezve #%s-ból/ből %s",
["chardisabled"] = "Karakter letiltva #%s-ból/ből %s",
["charnotfound"] = "Karakter #%s-ból/ből %s nem létezik",
["command_setslots"] = "Többszereplős slotok számának beállítása egy játékos számára",
["command_remslots"] = "Többszereplős slotok számának eltávolítása egy játékostól",
["command_enablechar"] = "Egy adott karakter engedélyezése egy játékosnál",
["command_disablechar"] = "Egy adott karakter letiltása egy játékosnál",
["command_charslot"] = "A karakter slot száma",
["command_identifier"] = "Játékos azonosító",
["command_slots"] = "Slotok száma",
["slotsadd"] = "%s slotot állítottál be %s játékosnak",
["slotsrem"] = "Eltávolítottad a slotokat %s játékostól",
["charenabled"] = "Engedélyezted a(z) #%s karaktert %s játékosnál",
["chardisabled"] = "Letiltottad a(z) #%s karaktert %s játékosnál",
["charnotfound"] = "A(z) #%s karakter %s játékosnál nem létezik",
UI = {
["title"] = "KARAKTER KIVÁLASZTÁSA",
["char_info_title"] = "Karakterinformáció",
["play"] = "JÁTÉK",
}
}

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