local lastSkin, cam, isCameraActive local firstSpawn, zoomOffset, camOffset, heading = true, 0.0, 0.0, 90.0 RegisterNetEvent("esx:playerLoaded") AddEventHandler("esx:playerLoaded", function(_, _, skin) TriggerServerEvent("ui_skin:setWeight", skin) end) function OpenMenu(submitCb, cancelCb, restrict) local playerPed = PlayerPedId() TriggerEvent("skinchanger:getSkin", function(skin) lastSkin = skin end) TriggerEvent("skinchanger:getData", function(components, maxVals) local elements = {} local _components = {} -- Restrict menu if restrict == nil then for i = 1, #components, 1 do _components[i] = components[i] end else for i = 1, #components, 1 do local found = false for j = 1, #restrict, 1 do if components[i].name == restrict[j] then found = true end end if found then table.insert(_components, components[i]) end end end -- Insert elements for i = 1, #_components, 1 do local value = _components[i].value local componentId = _components[i].componentId if componentId == 0 then value = GetPedPropIndex(playerPed, _components[i].componentId) end local data = { label = _components[i].label, name = _components[i].name, value = value, min = _components[i].min, textureof = _components[i].textureof, zoomOffset = _components[i].zoomOffset, camOffset = _components[i].camOffset, type = "slider", } for k, v in pairs(maxVals) do if k == _components[i].name then data.max = v break end end table.insert(elements, data) end CreateSkinCam() zoomOffset = _components[1].zoomOffset camOffset = _components[1].camOffset ESX.UI.Menu.Open("default", GetCurrentResourceName(), "skin", { title = TranslateCap("skin_menu"), align = "bottom-left", elements = elements, }, function(data, menu) TriggerEvent("skinchanger:getSkin", function(skin) lastSkin = skin end) submitCb(data, menu) DeleteSkinCam() end, function(data, menu) menu.close() DeleteSkinCam() TriggerEvent("skinchanger:loadSkin", lastSkin) if cancelCb ~= nil then cancelCb(data, menu) end end, function(data, menu) local skin, tempMaxVals TriggerEvent("skinchanger:getSkin", function(getSkin) skin = getSkin end) zoomOffset = data.current.zoomOffset camOffset = data.current.camOffset if skin[data.current.name] ~= data.current.value then -- Change skin element TriggerEvent("skinchanger:change", data.current.name, data.current.value) -- Update max values TriggerEvent("skinchanger:getData", function(comp, max) tempMaxVals = max end) local newData = {} for i = 1, #elements, 1 do newData.max = tempMaxVals[elements[i].name] if elements[i].textureof ~= nil and data.current.name == elements[i].textureof then newData.value = 0 end menu.update({ name = elements[i].name }, newData) end menu.refresh() end end, function() DeleteSkinCam() end) end) end function CreateSkinCam() if not DoesCamExist(cam) then cam = CreateCam("DEFAULT_SCRIPTED_CAMERA", true) end local playerPed = PlayerPedId() SetCamActive(cam, true) RenderScriptCams(true, true, 500, true, true) isCameraActive = true SetCamCoord(cam, GetEntityCoords(playerPed)) SetCamRot(cam, 0.0, 0.0, 270.0, true) SetEntityHeading(playerPed, 0.0) end function DeleteSkinCam() isCameraActive = false SetCamActive(cam, false) RenderScriptCams(false, true, 500, true, true) cam = nil end CreateThread(function() local customPI = math.pi / 180.0 while true do local sleep = 1500 if isCameraActive then sleep = 0 DisableControlAction(2, 30, true) DisableControlAction(2, 31, true) DisableControlAction(2, 32, true) DisableControlAction(2, 33, true) DisableControlAction(2, 34, true) DisableControlAction(2, 35, true) DisableControlAction(0, 25, true) -- Input Aim DisableControlAction(0, 24, true) -- Input Attack local playerPed = PlayerPedId() local coords = GetEntityCoords(playerPed) local angle = heading * customPI local theta = { x = math.cos(angle), y = math.sin(angle), } local pos = { x = coords.x + (zoomOffset * theta.x), y = coords.y + (zoomOffset * theta.y), } local angleToLook = heading - 140.0 if angleToLook > 360 then angleToLook = angleToLook - 360 elseif angleToLook < 0 then angleToLook = angleToLook + 360 end angleToLook = angleToLook * customPI local thetaToLook = { x = math.cos(angleToLook), y = math.sin(angleToLook), } local posToLook = { x = coords.x + (zoomOffset * thetaToLook.x), y = coords.y + (zoomOffset * thetaToLook.y), } SetCamCoord(cam, pos.x, pos.y, coords.z + camOffset) PointCamAtCoord(cam, posToLook.x, posToLook.y, coords.z + camOffset) ESX.ShowHelpNotification(TranslateCap("use_rotate_view")) end Wait(sleep) end end) CreateThread(function() local angle = 90 while true do local sleep = 1500 if isCameraActive then sleep = 0 if IsControlPressed(0, 209) then angle = angle - 1 elseif IsControlPressed(0, 19) then angle = angle + 1 end if angle > 360 then angle = angle - 360 elseif angle < 0 then angle = angle + 360 end heading = angle + 0.0 end Wait(sleep) end end) function OpenSaveableMenu(submitCb, cancelCb, restrict) TriggerEvent("skinchanger:getSkin", function(skin) lastSkin = skin end) OpenMenu(function(data, menu) menu.close() DeleteSkinCam() TriggerEvent("skinchanger:getSkin", function(skin) TriggerServerEvent("ui_skin:save", skin) if submitCb ~= nil then submitCb(data, menu) end end) end, cancelCb, restrict) end AddEventHandler("ui_skin:resetFirstSpawn", function() firstSpawn = true ESX.PlayerLoaded = false end) AddEventHandler("ui_skin:playerRegistered", function() CreateThread(function() while not ESX.PlayerLoaded do Wait(100) end if firstSpawn then ESX.TriggerServerCallback("ui_skin:getPlayerSkin", function(skin) if skin == nil then TriggerEvent("skinchanger:loadSkin", { sex = 0 }, OpenSaveableMenu) Wait(100) else TriggerEvent("skinchanger:loadSkin", skin) Wait(100) end end) firstSpawn = false end end) end) RegisterNetEvent("esx:playerLoaded") AddEventHandler("esx:playerLoaded", function() ESX.PlayerLoaded = true end) AddEventHandler("ui_skin:getLastSkin", function(cb) cb(lastSkin) end) AddEventHandler("ui_skin:setLastSkin", function(skin) lastSkin = skin end) RegisterNetEvent("ui_skin:openMenu") AddEventHandler("ui_skin:openMenu", function(submitCb, cancelCb) OpenMenu(submitCb, cancelCb, nil) end) RegisterNetEvent("ui_skin:openRestrictedMenu") AddEventHandler("ui_skin:openRestrictedMenu", function(submitCb, cancelCb, restrict) OpenMenu(submitCb, cancelCb, restrict) end) RegisterNetEvent("ui_skin:openSaveableMenu") AddEventHandler("ui_skin:openSaveableMenu", function(submitCb, cancelCb) OpenSaveableMenu(submitCb, cancelCb, nil) end) RegisterNetEvent("ui_skin:openSaveableRestrictedMenu") AddEventHandler("ui_skin:openSaveableRestrictedMenu", function(submitCb, cancelCb, restrict) OpenSaveableMenu(submitCb, cancelCb, restrict) end) RegisterNetEvent("ui_skin:requestSaveSkin") AddEventHandler("ui_skin:requestSaveSkin", function() TriggerEvent("skinchanger:getSkin", function(skin) TriggerServerEvent("ui_skin:responseSaveSkin", skin) end) end)