mirror of
https://github.com/esx-framework/esx_core.git
synced 2026-09-04 16:23:21 +00:00
fix skin / add accesories
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
local self = ESX.Modules['accessories']
|
||||
|
||||
self.Init()
|
||||
@@ -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
|
||||
@@ -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),
|
||||
}}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
Translations = {
|
||||
['valid_purchase'] = 'ověřit nákup?',
|
||||
['yes'] = 'ano (<span style="color: green;">$%s</span>)',
|
||||
['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~',
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
Translations = {
|
||||
['valid_purchase'] = 'validate this purchase?',
|
||||
['yes'] = 'yes (<span style="color: green;">$%s</span>)',
|
||||
['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~',
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
Translations = {
|
||||
['valid_purchase'] = 'varmista ostos?',
|
||||
['yes'] = 'kyllä (<span style="color: green;">$%s</span>)',
|
||||
['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~',
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
Translations = {
|
||||
['valid_purchase'] = 'valider cet achat?',
|
||||
['yes'] = 'oui (<span style="color: green;">$%s</span>)',
|
||||
['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~',
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
Translations = {
|
||||
['valid_purchase'] = 'czy napewno chcesz to zakupić?',
|
||||
['yes'] = 'tak (<span style="color: green;">%s $</span>)',
|
||||
['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~',
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
Translations = {
|
||||
['valid_purchase'] = 'Подтверждаете покупку',
|
||||
['yes'] = 'Да (<span style="color: green;">$%s</span>)',
|
||||
['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~',
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
Translations = {
|
||||
['valid_purchase'] = 'bekräfta köp?',
|
||||
['yes'] = 'ja (<span style="color: green;">%s SEK</span>)',
|
||||
['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~',
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
USE `es_extended`;
|
||||
|
||||
ALTER TABLE `users` ADD COLUMN `accessories` LONGTEXT NULL DEFAULT NULL;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
local self = ESX.Modules['accessories']
|
||||
|
||||
@@ -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']
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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öä',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
Reference in New Issue
Block a user