diff --git a/modules/accessories/client/events.lua b/modules/accessories/client/events.lua
new file mode 100644
index 00000000..346b4102
--- /dev/null
+++ b/modules/accessories/client/events.lua
@@ -0,0 +1,39 @@
+local self = ESX.Modules['accessories']
+
+local Input = ESX.Modules['input']
+
+AddEventHandler('esx_accessories:hasEnteredMarker', function(zone)
+ self.CurrentAction = 'shop_menu'
+ self.CurrentActionMsg = _U('press_access')
+ self.CurrentActionData = { accessory = zone }
+end)
+
+AddEventHandler('esx_accessories:hasExitedMarker', function(zone)
+ ESX.UI.Menu.CloseAll()
+ self.CurrentAction = nil
+end)
+
+-- Key Controls
+Input.On('released', Input.Groups.MOVE, Input.Controls.PICKUP, function(lastPressed)
+
+ if self.CurrentAction and (not ESX.IsDead) then
+ self.CurrentAction()
+ self.CurrentAction = nil
+ end
+
+end)
+
+if self.Config.EnableControls then
+
+ Input.On('released', Input.Groups.MOVE, Input.Controls.REPLAY_SHOWHOTKEY, function(lastPressed)
+
+ if not ESX.IsDead then
+ self.OpenAccessoryMenu()
+ end
+
+ end)
+
+end
+
+
+
diff --git a/modules/accessories/client/main.lua b/modules/accessories/client/main.lua
new file mode 100644
index 00000000..1fd054a6
--- /dev/null
+++ b/modules/accessories/client/main.lua
@@ -0,0 +1,3 @@
+local self = ESX.Modules['accessories']
+
+self.Init()
diff --git a/modules/accessories/client/module.lua b/modules/accessories/client/module.lua
new file mode 100644
index 00000000..84c16685
--- /dev/null
+++ b/modules/accessories/client/module.lua
@@ -0,0 +1,192 @@
+ESX.Modules['accessories'] = {}
+local self = ESX.Modules['accessories']
+
+-- Locals
+local Input = ESX.Modules['input']
+local Interact = ESX.Modules['interact']
+
+-- Properties
+self.Config = ESX.EvalFile(GetCurrentResourceName(), 'modules/accessories/data/config.lua', {
+ vector3 = vector3
+})['Config']
+
+
+self.Init = function()
+
+ self.RegisterControls()
+
+ local translations = ESX.EvalFile(GetCurrentResourceName(), 'modules/accessories/data/locales/' .. Config.Locale .. '.lua')['Translations']
+ LoadLocale('accessories', Config.Locale, translations)
+
+ for k,v in pairs(self.Config.Zones) do
+ for i = 1, #v.Pos, 1 do
+
+ local key = 'accessories:' .. k .. ':' .. i
+
+ Interact.Register({
+ name = key,
+ type = 'marker',
+ distance = self.Config.DrawDistance,
+ radius = 2.0,
+ pos = v.Pos[i],
+ size = self.Config.Size.z,
+ mtype = self.Config.Type,
+ color = self.Config.Color,
+ rotate = true,
+ accessory = k
+ })
+
+ AddEventHandler('esx:interact:enter:' .. key, function(data)
+
+ ESX.ShowHelpNotification(_U('accessories:press_access'))
+
+ self.CurrentAction = function()
+ self.OpenShopMenu(data.accessory)
+ end
+
+ end)
+
+ AddEventHandler('esx:interact:exit:' .. key, function(data)
+ self.CurrentAction = nil
+ end)
+
+ end
+ end
+
+ for k,v in pairs(self.Config.ShopsBlips) do
+ if v.Pos ~= nil then
+ for i=1, #v.Pos, 1 do
+ local blip = AddBlipForCoord(v.Pos[i])
+
+ SetBlipSprite (blip, v.Blip.sprite)
+ SetBlipDisplay(blip, 4)
+ SetBlipScale (blip, 1.0)
+ SetBlipColour (blip, v.Blip.color)
+ SetBlipAsShortRange(blip, true)
+
+ BeginTextCommandSetBlipName("STRING")
+ AddTextComponentString(_U('accessories:shop', _U(string.lower(k))))
+ EndTextCommandSetBlipName(blip)
+ end
+ end
+ end
+
+end
+
+self.OpenAccessoryMenu = function()
+ ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'set_unset_accessory', {
+ title = _U('accessories:set_unset'),
+ align = 'top-left',
+ elements = {
+ {label = _U('accessories:helmet'), value = 'Helmet'},
+ {label = _U('accessories:ears'), value = 'Ears'},
+ {label = _U('accessories:mask'), value = 'Mask'},
+ {label = _U('accessories:glasses'), value = 'Glasses'}
+ }}, function(data, menu)
+ menu.close()
+ self.SetUnsetAccessory(data.current.value)
+ end, function(data, menu)
+ menu.close()
+ end)
+end
+
+self.SetUnsetAccessory = function(accessory)
+ ESX.TriggerServerCallback('esx_accessories:get', function(hasAccessory, accessorySkin)
+ local _accessory = string.lower(accessory)
+
+ if hasAccessory then
+ TriggerEvent('skinchanger:getSkin', function(skin)
+ local mAccessory = -1
+ local mColor = 0
+
+ if _accessory == "mask" then
+ mAccessory = 0
+ end
+
+ if skin[_accessory .. '_1'] == mAccessory then
+ mAccessory = accessorySkin[_accessory .. '_1']
+ mColor = accessorySkin[_accessory .. '_2']
+ end
+
+ local accessorySkin = {}
+ accessorySkin[_accessory .. '_1'] = mAccessory
+ accessorySkin[_accessory .. '_2'] = mColor
+ TriggerEvent('skinchanger:loadClothes', skin, accessorySkin)
+ end)
+ else
+ ESX.ShowNotification(_U('accessories:no_' .. _accessory))
+ end
+ end, accessory)
+end
+
+self.OpenShopMenu = function(accessory)
+
+ local _accessory = string.lower(accessory)
+ local restrict = {}
+
+ restrict = { _accessory .. '_1', _accessory .. '_2' }
+
+ TriggerEvent('esx_skin:openRestrictedMenu', function(data, menu)
+
+ menu.close()
+
+ ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'shop_confirm', {
+ title = _U('accessories:valid_purchase'),
+ align = 'top-left',
+ elements = {
+ {label = _U('accessories:no'), value = 'no'},
+ {label = _U('accessories:yes', ESX.Math.GroupDigits(self.Config.Price)), value = 'yes'}
+ }}, function(data, menu)
+ menu.close()
+ if data.current.value == 'yes' then
+ ESX.TriggerServerCallback('esx_accessories:checkMoney', function(hasEnoughMoney)
+ if hasEnoughMoney then
+ TriggerServerEvent('esx_accessories:pay')
+ TriggerEvent('skinchanger:getSkin', function(skin)
+ TriggerServerEvent('esx_accessories:save', skin, accessory)
+ end)
+ else
+ TriggerEvent('esx_skin:getLastSkin', function(skin)
+ TriggerEvent('skinchanger:loadSkin', skin)
+ end)
+ ESX.ShowNotification(_U('accessories:not_enough_money'))
+ end
+ end)
+ end
+
+ if data.current.value == 'no' then
+ local player = PlayerPedId()
+ TriggerEvent('esx_skin:getLastSkin', function(skin)
+ TriggerEvent('skinchanger:loadSkin', skin)
+ end)
+ if accessory == "Ears" then
+ ClearPedProp(player, 2)
+ elseif accessory == "Mask" then
+ SetPedComponentVariation(player, 1, 0 ,0, 2)
+ elseif accessory == "Helmet" then
+ ClearPedProp(player, 0)
+ elseif accessory == "Glasses" then
+ SetPedPropIndex(player, 1, -1, 0, 0)
+ end
+ end
+ self.CurrentAction = 'shop_menu'
+ self.CurrentActionMsg = _U('accessories:press_access')
+ self.CurrentActionData = {}
+ end, function(data, menu)
+ menu.close()
+ self.CurrentAction = 'shop_menu'
+ self.CurrentActionMsg = _U('accessories:press_access')
+ self.CurrentActionData = {}
+ end)
+ end, function(data, menu)
+ menu.close()
+ self.CurrentAction = 'shop_menu'
+ self.CurrentActionMsg = _U('accessories:press_access')
+ self.CurrentActionData = {}
+ end, restrict)
+end
+
+self.RegisterControls = function()
+ Input.RegisterControl(Input.Groups.MOVE, Input.Controls.PICKUP)
+ Input.RegisterControl(Input.Groups.MOVE, Input.Controls.REPLAY_SHOWHOTKEY)
+end
diff --git a/modules/accessories/data/config.lua b/modules/accessories/data/config.lua
new file mode 100644
index 00000000..996e5af2
--- /dev/null
+++ b/modules/accessories/data/config.lua
@@ -0,0 +1,97 @@
+Config = {}
+
+Config.Locale = 'fr'
+
+Config.Price = 100
+
+Config.EnableControls = true
+
+Config.DrawDistance = 100.0
+Config.Size = {x = 1.5, y = 1.5, z = 1.0}
+Config.Color = {r = 102, g = 102, b = 204, a = 100}
+Config.Type = 1
+
+-- Fill this if you want to see the blips,
+-- If you have esx_clothesshop you should not fill this
+-- more than it's already filled.
+Config.ShopsBlips = {
+ Ears = {
+ Pos = nil,
+ Blip = nil
+ },
+ Mask = {
+ Pos = {
+ vector3(-1338.1, -1278.2, 3.8),
+ },
+ Blip = {sprite = 362, color = 2}
+ },
+ Helmet = {
+ Pos = nil,
+ Blip = nil
+ },
+ Glasses = {
+ Pos = nil,
+ Blip = nil
+ }
+}
+
+Config.Zones = {
+ Ears = {
+ Pos = {
+ vector3(80.3, -1389.4, 28.4),
+ vector3(-163.0, -302.0, 38.8),
+ vector3(-163.0,-302.0, 38.8),
+ vector3(420.7, -809.6, 28.6),
+ vector3(-817.0, -1075.9, 10.4),
+ vector3(-1451.3, -238.2, 48.9),
+ vector3(-0.7, 6513.6, 30.9),
+ vector3(123.4, -208.0, 53.6),
+ vector3(1687.3, 4827.6, 41.1),
+ vector3(622.8, 2749.2, 41.2),
+ vector3(1200.0, 2705.4, 37.3),
+ vector3(-1199.9, -782.5, 16.4),
+ vector3(-3171.8, 1059.6, 19.9),
+ vector3(-1095.6, 2709.2, 18.2),
+ }},
+
+ Mask = {
+ Pos = {
+ vector3(-1338.1, -1278.2, 3.8),
+ }},
+
+ Helmet = {
+ Pos = {
+ vector3(81.5, -1400.6, 28.4),
+ vector3(-705.8, -159.0, 36.5),
+ vector3(-161.3, -295.7, 38.8),
+ vector3(419.3, -800.6, 28.6),
+ vector3(-824.3, -1081.7, 10.4),
+ vector3(-1454.8, -242.9, 48.9),
+ vector3(4.7, 6520.9, 30.9),
+ vector3(121.0, -223.2, 53.3),
+ vector3(1689.6, 4818.8, 41.1),
+ vector3(613.9, 2749.9, 41.2),
+ vector3(1189.5, 2703.9, 37.3),
+ vector3(-1204.0, -774.4, 16.4),
+ vector3(-3164.2, 1054.7, 19.9),
+ vector3(-1103.1, 2700.5, 18.2),
+ }},
+
+ Glasses = {
+ Pos = {
+ vector3(75.2, -1391.1, 28.4),
+ vector3(-713.1, -160.1, 36.5),
+ vector3(-156.1, -300.5, 38.8),
+ vector3(425.4, -807.8, 28.6),
+ vector3(-820.8, -1072.9, 10.4),
+ vector3(-1458.0, -236.7, 48.9),
+ vector3(3.5, 6511.5, 30.9),
+ vector3(131.3, -212.3, 53.6),
+ vector3(1694.9, 4820.8, 41.1),
+ vector3(613.9, 2768.8, 41.2),
+ vector3(1198.6, 2711.0, 37.3),
+ vector3(-1188.2, -764.5, 16.4),
+ vector3(-3173.1, 1038.2, 19.9),
+ vector3(-1100.4, 2712.4, 18.2),
+ }}
+}
diff --git a/modules/accessories/data/locales/cs.lua b/modules/accessories/data/locales/cs.lua
new file mode 100644
index 00000000..46e2e60e
--- /dev/null
+++ b/modules/accessories/data/locales/cs.lua
@@ -0,0 +1,19 @@
+Translations = {
+ ['valid_purchase'] = 'ověřit nákup?',
+ ['yes'] = 'ano ($%s)',
+ ['no'] = 'ne',
+ ['helmet'] = 'helma / Čepice',
+ ['glasses'] = 'brýle',
+ ['mask'] = 'maska',
+ ['ears'] = 'doplňky na uši',
+ ['shop'] = '%s obchod',
+ ['set_unset'] = 'nasadit / Sundat',
+ ['not_enough_money'] = 'nemáte dostatek peněz',
+ ['press_access'] = 'zmáčkněte ~INPUT_CONTEXT~ pro otevření menu',
+ ['accessories_blip'] = 'doplňky',
+ ['no_ears'] = 'nemáte doplňky na uši',
+ ['no_glasses'] = 'nemáte brýle',
+ ['no_helmet'] = 'nemáte helmu',
+ ['no_mask'] = 'nemáte masku',
+ ['you_paid'] = 'zaplatili jste ~g~$%s~s~',
+}
diff --git a/modules/accessories/data/locales/en.lua b/modules/accessories/data/locales/en.lua
new file mode 100644
index 00000000..4af5bc93
--- /dev/null
+++ b/modules/accessories/data/locales/en.lua
@@ -0,0 +1,19 @@
+Translations = {
+ ['valid_purchase'] = 'validate this purchase?',
+ ['yes'] = 'yes ($%s)',
+ ['no'] = 'no',
+ ['helmet'] = 'helmet / Hat',
+ ['glasses'] = 'glasses',
+ ['mask'] = 'mask',
+ ['ears'] = 'ears accessories',
+ ['shop'] = '%s shop',
+ ['set_unset'] = 'put on / Take off',
+ ['not_enough_money'] = 'you do not have enough money',
+ ['press_access'] = 'press ~INPUT_CONTEXT~ to access the menu',
+ ['accessories_blip'] = 'accessories',
+ ['no_ears'] = 'you do not have ears accessories',
+ ['no_glasses'] = 'you do not have glasses',
+ ['no_helmet'] = 'you do not have a helmet',
+ ['no_mask'] = 'you do not have a mask',
+ ['you_paid'] = 'you paid ~g~$%s~s~',
+}
diff --git a/modules/accessories/data/locales/fi.lua b/modules/accessories/data/locales/fi.lua
new file mode 100644
index 00000000..3beffc97
--- /dev/null
+++ b/modules/accessories/data/locales/fi.lua
@@ -0,0 +1,19 @@
+Translations = {
+ ['valid_purchase'] = 'varmista ostos?',
+ ['yes'] = 'kyllä ($%s)',
+ ['no'] = 'ei',
+ ['helmet'] = 'kypärä / Hattu',
+ ['glasses'] = 'lasit',
+ ['mask'] = 'maskit',
+ ['ears'] = 'korva asusteet',
+ ['shop'] = '%s asustekauppa',
+ ['set_unset'] = 'laita päälle / Ota pois',
+ ['not_enough_money'] = 'sinulla ei ole tarpeeksi rahaa',
+ ['press_access'] = 'paina ~INPUT_CONTEXT~ avataksesi menu',
+ ['accessories_blip'] = 'asusteet',
+ ['no_ears'] = 'sinulla ei ole korva asusteita',
+ ['no_glasses'] = 'sinulla ei ole laseja',
+ ['no_helmet'] = 'sinulla ei ole kypäriä',
+ ['no_mask'] = 'sinulla ei ole maskeja',
+ ['you_paid'] = 'sinä maksoit ~g~$%s~s~',
+}
diff --git a/modules/accessories/data/locales/fr.lua b/modules/accessories/data/locales/fr.lua
new file mode 100644
index 00000000..445c6263
--- /dev/null
+++ b/modules/accessories/data/locales/fr.lua
@@ -0,0 +1,19 @@
+Translations = {
+ ['valid_purchase'] = 'valider cet achat?',
+ ['yes'] = 'oui ($%s)',
+ ['no'] = 'non',
+ ['helmet'] = 'casque / Chapeau',
+ ['glasses'] = 'lunettes',
+ ['mask'] = 'masque',
+ ['ears'] = 'accessoires d\'oreilles',
+ ['shop'] = '%s magasin de',
+ ['set_unset'] = 'mettre / Enlever',
+ ['not_enough_money'] = 'vous n\'avez pas assez d\'argent',
+ ['press_access'] = 'appuyez sur ~INPUT_CONTEXT~ pour accéder au menu',
+ ['accessories_blip'] = 'accessoires',
+ ['no_ears'] = 'vous n\'avez pas d\'accessoires d\'oreilles',
+ ['no_glasses'] = 'vous n\'avez pas de lunettes',
+ ['no_helmet'] = 'vous n\'avez pas de casque / chapeau',
+ ['no_mask'] = 'vous n\'avez pas de masque',
+ ['you_paid'] = 'vous avez payé ~g~$%s~s~',
+}
diff --git a/modules/accessories/data/locales/pl.lua b/modules/accessories/data/locales/pl.lua
new file mode 100644
index 00000000..bd393743
--- /dev/null
+++ b/modules/accessories/data/locales/pl.lua
@@ -0,0 +1,19 @@
+Translations = {
+ ['valid_purchase'] = 'czy napewno chcesz to zakupić?',
+ ['yes'] = 'tak (%s $)',
+ ['no'] = 'nie',
+ ['helmet'] = 'hełm / Czapka',
+ ['glasses'] = 'okulary',
+ ['mask'] = 'maska',
+ ['ears'] = 'akcesoria uszu',
+ ['shop'] = 'sklep %s ',
+ ['set_unset'] = 'załóż / Zdejmij',
+ ['not_enough_money'] = 'nie masz wystarczająco pieniędzy',
+ ['press_access'] = 'wciśnij ~INPUT_CONTEXT~ aby otworzyć menu',
+ ['accessories_blip'] = 'akcesoria',
+ ['no_ears'] = 'nie posiadasz akcesorii uszu',
+ ['no_glasses'] = 'nie posiadasz okularów',
+ ['no_helmet'] = 'nie posiadasz nakrycia głowy',
+ ['no_mask'] = 'nie posiadasz maski',
+ ['you_paid'] = 'płacisz ~g~%s $~s~',
+}
diff --git a/modules/accessories/data/locales/ru.lua b/modules/accessories/data/locales/ru.lua
new file mode 100644
index 00000000..bf955c77
--- /dev/null
+++ b/modules/accessories/data/locales/ru.lua
@@ -0,0 +1,19 @@
+Translations = {
+ ['valid_purchase'] = 'Подтверждаете покупку',
+ ['yes'] = 'Да ($%s)',
+ ['no'] = 'Нет',
+ ['helmet'] = 'Шлем / Шапка',
+ ['glasses'] = 'Очки',
+ ['mask'] = 'Маска',
+ ['ears'] = 'Аксессуары для ушей',
+ ['shop'] = 'Магазин %s',
+ ['set_unset'] = 'Положить / Снять',
+ ['not_enough_money'] = 'У вас не достаточно денег',
+ ['press_access'] = 'Нажмите ~INPUT_CONTEXT~ для доступа к меню',
+ ['accessories_blip'] = 'Аксессуары',
+ ['no_ears'] = 'У вас нет аксессуаров для ушей',
+ ['no_glasses'] = 'У вас нет очков',
+ ['no_helmet'] = 'У вас нет шлема',
+ ['no_mask'] = 'У вас нет маски',
+ ['you_paid'] = 'Вы заплатили ~g~$%s~s~',
+}
diff --git a/modules/accessories/data/locales/sv.lua b/modules/accessories/data/locales/sv.lua
new file mode 100644
index 00000000..4b8fafa6
--- /dev/null
+++ b/modules/accessories/data/locales/sv.lua
@@ -0,0 +1,19 @@
+Translations = {
+ ['valid_purchase'] = 'bekräfta köp?',
+ ['yes'] = 'ja (%s SEK)',
+ ['no'] = 'nej',
+ ['helmet'] = 'hjälm / hat',
+ ['glasses'] = 'glasögon',
+ ['mask'] = 'ansiktsmask',
+ ['ears'] = 'örontillbehör',
+ ['shop'] = '%s affär',
+ ['set_unset'] = 'ta på / av',
+ ['not_enough_money'] = 'du har inte råd!',
+ ['press_access'] = 'tryck ~INPUT_CONTEXT~ för att öppna menyn.',
+ ['accessories_blip'] = 'extrautröstning',
+ ['no_ears'] = 'du har inga öron tillbehör',
+ ['no_glasses'] = 'du har inga glasögon',
+ ['no_helmet'] = 'du har ingen hjälm',
+ ['no_mask'] = 'du har inte någon mask',
+ ['you_paid'] = 'du har betalat ~g~%s SEK~s~',
+}
diff --git a/modules/accessories/migrations/0.sql b/modules/accessories/migrations/0.sql
new file mode 100644
index 00000000..4a503e0f
--- /dev/null
+++ b/modules/accessories/migrations/0.sql
@@ -0,0 +1,4 @@
+USE `es_extended`;
+
+ALTER TABLE `users` ADD COLUMN `accessories` LONGTEXT NULL DEFAULT NULL;
+
diff --git a/modules/accessories/server/events.lua b/modules/accessories/server/events.lua
new file mode 100644
index 00000000..098df4bd
--- /dev/null
+++ b/modules/accessories/server/events.lua
@@ -0,0 +1,95 @@
+local self = ESX.Modules['accessories']
+
+-- BEGIN extend xPlayer stuff
+
+ -- add properties and methods to xPlayer when bulding its instance
+ AddEventHandler('esx:player:create', function(xPlayer)
+
+ xPlayer.set('getAccessories', function()
+ return xPlayer.get('accessories')
+ end)
+
+ xPlayer.set('setAccessories', function(accessories)
+ xPlayer.set('accessories', accessories)
+ end)
+
+ end)
+
+ -- add field when serializing xPlayer instance (for sending in event for example)
+ AddEventHandler('esx:player:serialize', function(xPlayer, add)
+ add({accessories = xPlayer.getAccessories()})
+ end)
+
+ -- add field when serializing xPlayer instance to DB
+ AddEventHandler('esx:player:serialize:db', function(xPlayer, add)
+ add({accessories = json.encode(xPlayer.getAccessories())})
+ end)
+
+ -- handle sql field loading from DB
+ AddEventHandler('esx:player:load:accessories', function(identifier, playerId, row, userData, addTask)
+
+ addTask(function(cb)
+
+ local data = {}
+
+ if row.accessories and row.accessories ~= '' then
+ data = json.decode(row.accessories)
+ else
+ data = {}
+ end
+
+ cb({accessories = data})
+
+ end)
+
+ end)
+
+-- END extend xPlayer stuff
+
+RegisterServerEvent('esx_accessories:pay')
+AddEventHandler('esx_accessories:pay', function()
+
+ local xPlayer = ESX.GetPlayerFromId(source)
+ xPlayer.removeMoney(self.Config.Price)
+ TriggerClientEvent('esx:showNotification', source, _U('you_paid', ESX.Math.GroupDigits(self.Config.Price)))
+
+end)
+
+RegisterServerEvent('esx_accessories:save')
+AddEventHandler('esx_accessories:save', function(skin, accessory)
+
+ local _source = source
+ local xPlayer = ESX.GetPlayerFromId(_source)
+
+ local item1 = string.lower(accessory) .. '_1'
+ local item2 = string.lower(accessory) .. '_2'
+
+ local accessories = xPlayer.getAccessories()
+
+ accessories[accessory] = {
+ [item1] = skin[item1],
+ [item2] = skin[item2],
+ }
+
+ xPlayer.setAccessories(accessories)
+
+end)
+
+ESX.RegisterServerCallback('esx_accessories:get', function(source, cb, accessory)
+
+ local xPlayer = ESX.GetPlayerFromId(source)
+
+ local skin = xPlayer.accessories[accessory]
+ local hasAccessory = skin ~= nil
+
+ cb(hasAccessory, skin)
+
+end)
+
+ESX.RegisterServerCallback('esx_accessories:checkMoney', function(source, cb)
+
+ local xPlayer = ESX.GetPlayerFromId(source)
+ cb(xPlayer.getMoney() >= self.Config.Price)
+
+end)
+
diff --git a/modules/accessories/server/main.lua b/modules/accessories/server/main.lua
new file mode 100644
index 00000000..6efe85e2
--- /dev/null
+++ b/modules/accessories/server/main.lua
@@ -0,0 +1,2 @@
+local self = ESX.Modules['accessories']
+
diff --git a/modules/accessories/server/module.lua b/modules/accessories/server/module.lua
new file mode 100644
index 00000000..dbb471a6
--- /dev/null
+++ b/modules/accessories/server/module.lua
@@ -0,0 +1,8 @@
+ESX.Modules['accessories'] = {}
+local self = ESX.Modules['accessories']
+
+-- Properties
+self.Config = ESX.EvalFile(GetCurrentResourceName(), 'modules/accessories/data/config.lua', {
+ vector3 = vector3
+})['Config']
+
diff --git a/modules/skin/client/main.lua b/modules/skin/client/main.lua
index 4fec8c44..1f8d2d79 100644
--- a/modules/skin/client/main.lua
+++ b/modules/skin/client/main.lua
@@ -1,5 +1,7 @@
local self = ESX.Modules['skin']
+self.Init()
+
Citizen.CreateThread(function()
while true do
@@ -18,39 +20,42 @@ Citizen.CreateThread(function()
local playerPed = PlayerPedId()
local coords = GetEntityCoords(playerPed)
- local angle = heading * math.pi / 180.0
+ local angle = self.heading * math.pi / 180.0
local theta = {
x = math.cos(angle),
y = math.sin(angle)
}
local pos = {
- x = coords.x + (zoomOffset * theta.x),
- y = coords.y + (zoomOffset * theta.y)
+ x = coords.x + (self.zoomOffset * theta.x),
+ y = coords.y + (self.zoomOffset * theta.y)
}
- local angleToLook = heading - 140.0
+ local angleToLook = self.heading - 140.0
+
if angleToLook > 360 then
angleToLook = angleToLook - 360
elseif angleToLook < 0 then
angleToLook = angleToLook + 360
end
- angleToLook = angleToLook * math.pi / 180.0
+ angleToLook = angleToLook * math.pi / 180.0
+
local thetaToLook = {
x = math.cos(angleToLook),
y = math.sin(angleToLook)
}
local posToLook = {
- x = coords.x + (zoomOffset * thetaToLook.x),
- y = coords.y + (zoomOffset * thetaToLook.y)
+ x = coords.x + (self.zoomOffset * thetaToLook.x),
+ y = coords.y + (self.zoomOffset * thetaToLook.y)
}
- SetCamCoord(cam, pos.x, pos.y, coords.z + camOffset)
- PointCamAtCoord(cam, posToLook.x, posToLook.y, coords.z + camOffset)
+ SetCamCoord(self.cam, pos.x, pos.y, coords.z + self.camOffset)
+ PointCamAtCoord(self.cam, posToLook.x, posToLook.y, coords.z + self.camOffset)
+
+ ESX.ShowHelpNotification(_U('use_rotate_view'))
- ESX.ShowHelpNotification(_U('use_rotate_view'))
else
Citizen.Wait(500)
end
diff --git a/modules/skin/client/module.lua b/modules/skin/client/module.lua
index 9331ed52..cdd2d489 100644
--- a/modules/skin/client/module.lua
+++ b/modules/skin/client/module.lua
@@ -10,6 +10,14 @@ self.firstSpawn = true
self.zoomOffset = 0.0
self.camOffset = 0.0
self.heading = 90.0
+self.angle = 0.0
+
+self.Init = function()
+
+ local translations = ESX.EvalFile(GetCurrentResourceName(), 'modules/skin/data/locales/' .. Config.Locale .. '.lua')['Translations']
+ LoadLocale('skin', Config.Locale, translations)
+
+end
self.OpenMenu = function(submitCb, cancelCb, restrict)
@@ -79,7 +87,7 @@ self.OpenMenu = function(submitCb, cancelCb, restrict)
self.camOffset = _components[1].camOffset
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'skin', {
- title = _U('skin_menu'),
+ title = _U('skin:skin_menu'),
align = 'top-left',
elements = elements
}, function(data, menu)
@@ -132,27 +140,30 @@ self.OpenMenu = function(submitCb, cancelCb, restrict)
menu.refresh()
end
end, function(data, menu)
- DeleteSkinCam()
+ self.DeleteSkinCam()
end)
end)
end
self.CreateSkinCam = function()
- if not DoesCamExist(cam) then
+
+ local playerPed = PlayerPedId()
+
+ if not DoesCamExist(self.cam) then
self.cam = CreateCam('DEFAULT_SCRIPTED_CAMERA', true)
end
- SetCamActive(cam, true)
+ SetCamActive(self.cam, true)
RenderScriptCams(true, true, 500, true, true)
self.isCameraActive = true
- SetCamRot(cam, 0.0, 0.0, 270.0, true)
+ SetCamRot(self.cam, 0.0, 0.0, 270.0, true)
SetEntityHeading(playerPed, 90.0)
end
self.DeleteSkinCam = function()
self.isCameraActive = false
- SetCamActive(cam, false)
+ SetCamActive(self.cam, false)
RenderScriptCams(false, true, 500, true, true)
cam = nil
end
@@ -164,7 +175,7 @@ self.OpenSaveableMenu = function(submitCb, cancelCb, restrict)
self.OpenMenu(function(data, menu)
menu.close()
- DeleteSkinCam()
+ self.DeleteSkinCam()
TriggerEvent('skinchanger:getSkin', function(skin)
TriggerServerEvent('esx_skin:save', skin)
diff --git a/modules/skin/data/locales/br.lua b/modules/skin/data/locales/br.lua
index 2a9d09d4..82796932 100644
--- a/modules/skin/data/locales/br.lua
+++ b/modules/skin/data/locales/br.lua
@@ -1,4 +1,4 @@
-Locales['br'] = {
+Translations = {
['skin_menu'] = 'Skin Menu',
['use_rotate_view'] = 'Use ~INPUT_VEH_FLY_ROLL_LEFT_ONLY~ e ~INPUT_VEH_FLY_ROLL_RIGHT_ONLY~ para girar a visão.',
['skin'] = 'Trocar',
diff --git a/modules/skin/data/locales/de.lua b/modules/skin/data/locales/de.lua
index f1439358..ed7c718d 100644
--- a/modules/skin/data/locales/de.lua
+++ b/modules/skin/data/locales/de.lua
@@ -1,4 +1,4 @@
-Locales['de'] = {
+Translations = {
['skin_menu'] = 'Skin Menü',
['use_rotate_view'] = 'benutze ~INPUT_VEH_FLY_ROLL_LEFT_ONLY~ und ~INPUT_VEH_FLY_ROLL_RIGHT_ONLY~ um die Sicht zu drehen.',
['skin'] = 'Skin ändern',
diff --git a/modules/skin/data/locales/en.lua b/modules/skin/data/locales/en.lua
index f1ee073e..eae6a78c 100644
--- a/modules/skin/data/locales/en.lua
+++ b/modules/skin/data/locales/en.lua
@@ -1,4 +1,4 @@
-Locales['en'] = {
+Translations = {
['skin_menu'] = 'Skin Menu',
['use_rotate_view'] = 'use ~INPUT_VEH_FLY_ROLL_LEFT_ONLY~ and ~INPUT_VEH_FLY_ROLL_RIGHT_ONLY~ to rotate the view.',
['skin'] = 'change skin',
diff --git a/modules/skin/data/locales/fi.lua b/modules/skin/data/locales/fi.lua
index 39e6d75f..df2b4ee1 100644
--- a/modules/skin/data/locales/fi.lua
+++ b/modules/skin/data/locales/fi.lua
@@ -1,4 +1,4 @@
-Locales['fi'] = {
+Translations = {
['skin_menu'] = 'ulkonäkö',
['use_rotate_view'] = 'paina ~INPUT_VEH_FLY_ROLL_LEFT_ONLY~ tai ~INPUT_VEH_FLY_ROLL_RIGHT_ONLY~ liikutaaksesi kameraa.',
['skin'] = 'vaihda ulkonäköä',
diff --git a/modules/skin/data/locales/fr.lua b/modules/skin/data/locales/fr.lua
index 22cfc7bc..f48bb191 100644
--- a/modules/skin/data/locales/fr.lua
+++ b/modules/skin/data/locales/fr.lua
@@ -1,4 +1,4 @@
-Locales['fr'] = {
+Translations = {
['skin_menu'] = 'Skin Menu',
['use_rotate_view'] = 'utilisez ~INPUT_VEH_FLY_ROLL_LEFT_ONLY~ et ~INPUT_VEH_FLY_ROLL_RIGHT_ONLY~ pour tourner la vue.',
['skin'] = 'changer de skin',
diff --git a/modules/skin/data/locales/pl.lua b/modules/skin/data/locales/pl.lua
index 9458a7a4..9d6ed9f8 100644
--- a/modules/skin/data/locales/pl.lua
+++ b/modules/skin/data/locales/pl.lua
@@ -1,4 +1,4 @@
-Locales['pl'] = {
+Translations = {
['skin_menu'] = 'menu wyglądu',
['use_rotate_view'] = 'użyj ~INPUT_VEH_FLY_ROLL_LEFT_ONLY~ i ~INPUT_VEH_FLY_ROLL_RIGHT_ONLY~ aby obrócić ekran.',
['skin'] = 'zmień wygląd',
diff --git a/modules/skin/data/locales/sv.lua b/modules/skin/data/locales/sv.lua
index 02ddd5f0..46f089ef 100644
--- a/modules/skin/data/locales/sv.lua
+++ b/modules/skin/data/locales/sv.lua
@@ -1,4 +1,4 @@
-Locales['sv'] = {
+Translations = {
['skin_menu'] = 'skin meny',
['use_rotate_view'] = 'använd ~INPUT_VEH_FLY_ROLL_LEFT_ONLY~ och ~INPUT_VEH_FLY_ROLL_RIGHT_ONLY~ för att rotera.',
['skin'] = 'ändra skin',
diff --git a/modules/skin/server/events.lua b/modules/skin/server/events.lua
index ffbbeb66..94690aca 100644
--- a/modules/skin/server/events.lua
+++ b/modules/skin/server/events.lua
@@ -34,11 +34,13 @@ AddEventHandler('esx_skin:responseSaveSkin', function(skin)
end)
ESX.RegisterServerCallback('esx_skin:getPlayerSkin', function(source, cb)
- local xPlayer = ESX.GetPlayerFromId(source)
+
+ local xPlayer = ESX.GetPlayerFromId(source)
MySQL.Async.fetchAll('SELECT skin FROM users WHERE identifier = @identifier', {
['@identifier'] = xPlayer.identifier
- }, function(users)
+ }, function(users)
+
local user, skin = users[1]
local jobSkin = {