613 lines
		
	
	
	
		
			18 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			613 lines
		
	
	
	
		
			18 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| local reverseCamera
 | |
| 
 | |
| local function getRgbColors()
 | |
|     local colors = {
 | |
|         hair = {},
 | |
|         makeUp = {}
 | |
|     }
 | |
| 
 | |
|     for i = 0, GetNumHairColors() - 1 do
 | |
|         colors.hair[i+1] = {GetPedHairRgbColor(i)}
 | |
|     end
 | |
| 
 | |
|     for i = 0, GetNumMakeupColors() - 1 do
 | |
|         colors.makeUp[i+1] = {GetPedMakeupRgbColor(i)}
 | |
|     end
 | |
| 
 | |
|     return colors
 | |
| end
 | |
| 
 | |
| local playerAppearance
 | |
| 
 | |
| local function getAppearance()
 | |
|     if not playerAppearance then
 | |
|         playerAppearance = client.getPedAppearance(cache.ped)
 | |
|     end
 | |
| 
 | |
|     return playerAppearance
 | |
| end
 | |
| client.getAppearance = getAppearance
 | |
| 
 | |
| local function addToBlacklist(item, drawable, drawableId, blacklistSettings)
 | |
|     if drawable == drawableId and item.textures then
 | |
|         for i = 1, #item.textures do
 | |
|             blacklistSettings.textures[#blacklistSettings.textures + 1] = item.textures[i]
 | |
|         end
 | |
|     end
 | |
|     if not item.textures or #item.textures == 0 then
 | |
|         blacklistSettings.drawables[#blacklistSettings.drawables + 1] = drawable
 | |
|     end
 | |
| end
 | |
| 
 | |
| local function listContains(items, item)
 | |
|     for i = 1, #items do
 | |
|         if items[i] == item then
 | |
|             return true
 | |
|         end
 | |
|     end
 | |
|     return false
 | |
| end
 | |
| 
 | |
| local function listContainsAny(items, containedItems)
 | |
|     for i = 1, #items do
 | |
|         if listContains(containedItems, items[i]) then
 | |
|             return true
 | |
|         end
 | |
|     end
 | |
|     return false
 | |
| end
 | |
| 
 | |
| local function allowedForPlayer(item, allowedAces)
 | |
|     return (item.jobs and listContains(item.jobs, client.job.name)) or (item.gangs and listContains(item.gangs, client.gang.name)) or (item.aces and listContainsAny(item.aces, allowedAces) or (item.citizenids and listContains(item.citizenids, client.citizenid)))
 | |
| end
 | |
| 
 | |
| local function filterPedModelsForPlayer(pedConfigs)
 | |
|     local playerPeds = {}
 | |
|     local allowedAces = lib.callback.await("illenium-appearance:server:GetPlayerAces", false)
 | |
| 
 | |
|     for i = 1, #pedConfigs do
 | |
|         local config = pedConfigs[i]
 | |
|         if (not config.jobs and not config.gangs and not config.aces and not config.citizenids) or allowedForPlayer(config, allowedAces) then
 | |
|             for j = 1, #config.peds do
 | |
|                 playerPeds[#playerPeds + 1] = config.peds[j]
 | |
|             end
 | |
|         end
 | |
|     end
 | |
|     return playerPeds
 | |
| end
 | |
| 
 | |
| local function filterTattoosByGender(tattoos)
 | |
|     local filtered = {}
 | |
|     local gender = client.getPedDecorationType()
 | |
|     for k, v in pairs(tattoos) do
 | |
|         filtered[k] = {}
 | |
|         for i = 1, #v do
 | |
|             local tattoo = v[i]
 | |
|             if tattoo["hash" .. gender:gsub("^%l", string.upper)] ~= "" then
 | |
|                 filtered[k][#filtered[k] + 1] = tattoo
 | |
|             end
 | |
|         end
 | |
|     end
 | |
|     return filtered
 | |
| end
 | |
| 
 | |
| local function filterBlacklistSettings(items, drawableId)
 | |
|     local blacklistSettings = {
 | |
|         drawables = {},
 | |
|         textures = {}
 | |
|     }
 | |
| 
 | |
|     local allowedAces = lib.callback.await("illenium-appearance:server:GetPlayerAces", false)
 | |
| 
 | |
|     for i = 1, #items do
 | |
|         local item = items[i]
 | |
|         if not allowedForPlayer(item, allowedAces) and item.drawables then
 | |
|             for j = 0, #item.drawables do
 | |
|                 addToBlacklist(item, item.drawables[j], drawableId, blacklistSettings)
 | |
|             end
 | |
|         end
 | |
|     end
 | |
| 
 | |
|     return blacklistSettings
 | |
| end
 | |
| 
 | |
| local function componentBlacklistMap(gender, componentId)
 | |
|     local genderSettings = Config.Blacklist[gender].components
 | |
|     if componentId == 1 then
 | |
|         return genderSettings.masks
 | |
|     elseif componentId == 3 then
 | |
|         return genderSettings.upperBody
 | |
|     elseif componentId == 4 then
 | |
|         return genderSettings.lowerBody
 | |
|     elseif componentId == 5 then
 | |
|         return genderSettings.bags
 | |
|     elseif componentId == 6 then
 | |
|         return genderSettings.shoes
 | |
|     elseif componentId == 7 then
 | |
|         return genderSettings.scarfAndChains
 | |
|     elseif componentId == 8 then
 | |
|         return genderSettings.shirts
 | |
|     elseif componentId == 9 then
 | |
|         return genderSettings.bodyArmor
 | |
|     elseif componentId == 10 then
 | |
|         return genderSettings.decals
 | |
|     elseif componentId == 11 then
 | |
|         return genderSettings.jackets
 | |
|     end
 | |
| 
 | |
|     return {}
 | |
| end
 | |
| 
 | |
| local function propBlacklistMap(gender, propId)
 | |
|     local genderSettings = Config.Blacklist[gender].props
 | |
| 
 | |
|     if propId == 0 then
 | |
|         return genderSettings.hats
 | |
|     elseif propId == 1 then
 | |
|         return genderSettings.glasses
 | |
|     elseif propId == 2 then
 | |
|         return genderSettings.ear
 | |
|     elseif propId == 6 then
 | |
|         return genderSettings.watches
 | |
|     elseif propId == 7 then
 | |
|         return genderSettings.bracelets
 | |
|     end
 | |
| 
 | |
|     return {}
 | |
| end
 | |
| 
 | |
| local function getComponentSettings(ped, componentId)
 | |
|     local drawableId = GetPedDrawableVariation(ped, componentId)
 | |
|     local gender = client.getPedDecorationType()
 | |
| 
 | |
|     local blacklistSettings = {
 | |
|         drawables = {},
 | |
|         textures = {}
 | |
|     }
 | |
| 
 | |
|     if client.isPedFreemodeModel(ped) then
 | |
|         blacklistSettings = filterBlacklistSettings(componentBlacklistMap(gender, componentId), drawableId)
 | |
|     end
 | |
| 
 | |
|     return {
 | |
|         component_id = componentId,
 | |
|         drawable = {
 | |
|             min = 0,
 | |
|             max = GetNumberOfPedDrawableVariations(ped, componentId) - 1
 | |
|         },
 | |
|         texture = {
 | |
|             min = 0,
 | |
|             max = GetNumberOfPedTextureVariations(ped, componentId, drawableId) - 1
 | |
|         },
 | |
|         blacklist = blacklistSettings
 | |
|     }
 | |
| end
 | |
| client.getComponentSettings = getComponentSettings
 | |
| 
 | |
| local function getPropSettings(ped, propId)
 | |
|     local drawableId = GetPedPropIndex(ped, propId)
 | |
|     local gender = client.getPedDecorationType()
 | |
| 
 | |
|     local blacklistSettings = {
 | |
|         drawables = {},
 | |
|         textures = {}
 | |
|     }
 | |
| 
 | |
|     if client.isPedFreemodeModel(ped) then
 | |
|         blacklistSettings = filterBlacklistSettings(propBlacklistMap(gender, propId), drawableId)
 | |
|     end
 | |
| 
 | |
|     local settings = {
 | |
|         prop_id = propId,
 | |
|         drawable = {
 | |
|             min = -1,
 | |
|             max = GetNumberOfPedPropDrawableVariations(ped, propId) - 1
 | |
|         },
 | |
|         texture = {
 | |
|             min = -1,
 | |
|             max = GetNumberOfPedPropTextureVariations(ped, propId, drawableId) - 1
 | |
|         },
 | |
|         blacklist = blacklistSettings
 | |
|     }
 | |
|     return settings
 | |
| end
 | |
| client.getPropSettings = getPropSettings
 | |
| 
 | |
| local function getHairSettings(ped)
 | |
|     local colors = getRgbColors()
 | |
|     local gender = client.getPedDecorationType()
 | |
|     local blacklistSettings = {
 | |
|         drawables = {},
 | |
|         textures = {}
 | |
|     }
 | |
| 
 | |
|     if client.isPedFreemodeModel(ped) then
 | |
|         blacklistSettings = filterBlacklistSettings(Config.Blacklist[gender].hair, GetPedDrawableVariation(ped, 2))
 | |
|     end
 | |
| 
 | |
|     local settings = {
 | |
|         style = {
 | |
|             min = 0,
 | |
|             max = GetNumberOfPedDrawableVariations(ped, 2) - 1
 | |
|         },
 | |
|         color = {
 | |
|             items = colors.hair
 | |
|         },
 | |
|         highlight = {
 | |
|             items = colors.hair
 | |
|         },
 | |
|         texture = {
 | |
|             min = 0,
 | |
|             max = GetNumberOfPedTextureVariations(ped, 2, GetPedDrawableVariation(ped, 2)) - 1
 | |
|         },
 | |
|         blacklist = blacklistSettings
 | |
|     }
 | |
| 
 | |
|     return settings
 | |
| end
 | |
| client.getHairSettings = getHairSettings
 | |
| 
 | |
| local function getAppearanceSettings()
 | |
|     local ped = {
 | |
|         model = {
 | |
|             items = filterPedModelsForPlayer(Config.Peds.pedConfig)
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     local tattoos = {
 | |
|         items = filterTattoosByGender(Config.Tattoos),
 | |
|         opacity = {
 | |
|             min = 0.1,
 | |
|             max = 1,
 | |
|             factor = 0.1,
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     local components = {}
 | |
|     for i = 1, #constants.PED_COMPONENTS_IDS do
 | |
|         components[i] = getComponentSettings(cache.ped, constants.PED_COMPONENTS_IDS[i])
 | |
|     end
 | |
| 
 | |
|     local props = {}
 | |
|     for i = 1, #constants.PED_PROPS_IDS do
 | |
|         props[i] = getPropSettings(cache.ped, constants.PED_PROPS_IDS[i])
 | |
|     end
 | |
| 
 | |
|     local headBlend = {
 | |
|         shapeFirst = {
 | |
|             min = 0,
 | |
|             max = 45
 | |
|         },
 | |
|         shapeSecond = {
 | |
|             min = 0,
 | |
|             max = 45
 | |
|         },
 | |
|         shapeThird = {
 | |
|             min = 0,
 | |
|             max = 45
 | |
|         },
 | |
|         skinFirst = {
 | |
|             min = 0,
 | |
|             max = 45
 | |
|         },
 | |
|         skinSecond = {
 | |
|             min = 0,
 | |
|             max = 45
 | |
|         },
 | |
|         skinThird = {
 | |
|             min = 0,
 | |
|             max = 45
 | |
|         },
 | |
|         shapeMix = {
 | |
|             min = 0,
 | |
|             max = 1,
 | |
|             factor = 0.1,
 | |
|         },
 | |
|         skinMix = {
 | |
|             min = 0,
 | |
|             max = 1,
 | |
|             factor = 0.1,
 | |
|         },
 | |
|         thirdMix = {
 | |
|             min = 0,
 | |
|             max = 1,
 | |
|             factor = 0.1,
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     local size = #constants.FACE_FEATURES
 | |
|     local faceFeatures = table.create(0, size)
 | |
|     for i = 1, size do
 | |
|         local feature = constants.FACE_FEATURES[i]
 | |
|         faceFeatures[feature] = { min = -1, max = 1, factor = 0.1}
 | |
|     end
 | |
| 
 | |
|     local colors = getRgbColors()
 | |
| 
 | |
|     local colorMap = {
 | |
|         beard = colors.hair,
 | |
|         eyebrows = colors.hair,
 | |
|         chestHair = colors.hair,
 | |
|         makeUp = colors.makeUp,
 | |
|         blush = colors.makeUp,
 | |
|         lipstick = colors.makeUp,
 | |
|     }
 | |
| 
 | |
|     size = #constants.HEAD_OVERLAYS
 | |
|     local headOverlays = table.create(0, size)
 | |
| 
 | |
|     for i = 1, size do
 | |
|         local overlay = constants.HEAD_OVERLAYS[i]
 | |
|         local settings = {
 | |
|             style = {
 | |
|                 min = 0,
 | |
|                 max = GetPedHeadOverlayNum(i - 1) - 1
 | |
|             },
 | |
|             opacity = {
 | |
|                 min = 0,
 | |
|                 max = 1,
 | |
|                 factor = 0.1,
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if colorMap[overlay] then
 | |
|             settings.color = {
 | |
|                 items = colorMap[overlay]
 | |
|             }
 | |
|         end
 | |
| 
 | |
|         headOverlays[overlay] = settings
 | |
|     end
 | |
| 
 | |
|     local eyeColor = {
 | |
|         min = 0,
 | |
|         max = 30
 | |
|     }
 | |
| 
 | |
|     return {
 | |
|         ped = ped,
 | |
|         components = components,
 | |
|         props = props,
 | |
|         headBlend = headBlend,
 | |
|         faceFeatures = faceFeatures,
 | |
|         headOverlays = headOverlays,
 | |
|         hair = getHairSettings(cache.ped),
 | |
|         eyeColor = eyeColor,
 | |
|         tattoos = tattoos
 | |
|     }
 | |
| end
 | |
| client.getAppearanceSettings = getAppearanceSettings
 | |
| 
 | |
| local config
 | |
| function client.getConfig() return config end
 | |
| 
 | |
| local isCameraInterpolating
 | |
| local currentCamera
 | |
| local cameraHandle
 | |
| local function setCamera(key)
 | |
|     if not isCameraInterpolating then
 | |
|         if key ~= "current" then
 | |
|             currentCamera = key
 | |
|         end
 | |
| 
 | |
|         local coords, point = table.unpack(constants.CAMERAS[currentCamera])
 | |
|         local reverseFactor = reverseCamera and -1 or 1
 | |
| 
 | |
|         if cameraHandle then
 | |
|             local camCoords = GetOffsetFromEntityInWorldCoords(cache.ped, coords.x * reverseFactor, coords.y * reverseFactor, coords.z * reverseFactor)
 | |
|             local camPoint = GetOffsetFromEntityInWorldCoords(cache.ped, point.x, point.y, point.z)
 | |
|             local tmpCamera = CreateCameraWithParams("DEFAULT_SCRIPTED_CAMERA", camCoords.x, camCoords.y, camCoords.z, 0.0, 0.0, 0.0, 49.0, false, 0)
 | |
| 
 | |
|             PointCamAtCoord(tmpCamera, camPoint.x, camPoint.y, camPoint.z)
 | |
|             SetCamActiveWithInterp(tmpCamera, cameraHandle, 1000, 1, 1)
 | |
| 
 | |
|             isCameraInterpolating = true
 | |
| 
 | |
|             CreateThread(function()
 | |
|                 repeat Wait(500)
 | |
|                 until not IsCamInterpolating(cameraHandle) and IsCamActive(tmpCamera)
 | |
|                 DestroyCam(cameraHandle, false)
 | |
|                 cameraHandle = tmpCamera
 | |
|                 isCameraInterpolating = false
 | |
|             end)
 | |
|         else
 | |
|             local camCoords = GetOffsetFromEntityInWorldCoords(cache.ped, coords.x, coords.y, coords.z)
 | |
|             local camPoint = GetOffsetFromEntityInWorldCoords(cache.ped, point.x, point.y, point.z)
 | |
|             cameraHandle = CreateCameraWithParams("DEFAULT_SCRIPTED_CAMERA", camCoords.x, camCoords.y, camCoords.z, 0.0, 0.0, 0.0, 49.0, false, 0)
 | |
| 
 | |
|             PointCamAtCoord(cameraHandle, camPoint.x, camPoint.y, camPoint.z)
 | |
|             SetCamActive(cameraHandle, true)
 | |
|         end
 | |
|     end
 | |
| end
 | |
| client.setCamera = setCamera
 | |
| 
 | |
| function client.rotateCamera(direction)
 | |
|     if not isCameraInterpolating then
 | |
|         local coords, point = table.unpack(constants.CAMERAS[currentCamera])
 | |
|         local offset = constants.OFFSETS[currentCamera]
 | |
|         local sideFactor = direction == "left" and 1 or -1
 | |
|         local reverseFactor = reverseCamera and -1 or 1
 | |
| 
 | |
|         local camCoords = GetOffsetFromEntityInWorldCoords(
 | |
|             cache.ped,
 | |
|             (coords.x + offset.x) * sideFactor * reverseFactor,
 | |
|             (coords.y + offset.y) * reverseFactor,
 | |
|             coords.z
 | |
|         )
 | |
| 
 | |
|         local camPoint = GetOffsetFromEntityInWorldCoords(cache.ped, point.x, point.y, point.z)
 | |
|         local tmpCamera = CreateCameraWithParams("DEFAULT_SCRIPTED_CAMERA", camCoords.x, camCoords.y, camCoords.z, 0.0, 0.0, 0.0, 49.0, false, 0)
 | |
| 
 | |
|         PointCamAtCoord(tmpCamera, camPoint.x, camPoint.y, camPoint.z)
 | |
|         SetCamActiveWithInterp(tmpCamera, cameraHandle, 1000, 1, 1)
 | |
| 
 | |
|         isCameraInterpolating = true
 | |
| 
 | |
|         CreateThread(function()
 | |
|             repeat Wait(500)
 | |
|             until not IsCamInterpolating(cameraHandle) and IsCamActive(tmpCamera)
 | |
|             DestroyCam(cameraHandle, false)
 | |
|             cameraHandle = tmpCamera
 | |
|             isCameraInterpolating = false
 | |
|         end)
 | |
|     end
 | |
| end
 | |
| 
 | |
| local playerCoords
 | |
| local function pedTurn(ped, angle)
 | |
|     reverseCamera = not reverseCamera
 | |
|     local sequenceTaskId = OpenSequenceTask()
 | |
|     if sequenceTaskId then
 | |
|         TaskGoStraightToCoord(0, playerCoords.x, playerCoords.y, playerCoords.z, 8.0, -1, GetEntityHeading(ped) - angle, 0.1)
 | |
|         TaskStandStill(0, -1)
 | |
|         CloseSequenceTask(sequenceTaskId)
 | |
|         ClearPedTasks(ped)
 | |
|         TaskPerformSequence(ped, sequenceTaskId)
 | |
|         ClearSequenceTask(sequenceTaskId)
 | |
|     end
 | |
| end
 | |
| client.pedTurn = pedTurn
 | |
| 
 | |
| local function wearClothes(data, typeClothes)
 | |
|     local dataClothes = constants.DATA_CLOTHES[typeClothes]
 | |
|     local animationsOn = dataClothes.animations.on
 | |
|     local components = dataClothes.components[client.getPedDecorationType()]
 | |
|     local appliedComponents = data.components
 | |
|     local props = dataClothes.props[client.getPedDecorationType()]
 | |
|     local appliedProps = data.props
 | |
| 
 | |
|     RequestAnimDict(animationsOn.dict)
 | |
|     while not HasAnimDictLoaded(animationsOn.dict) do
 | |
|         Wait(0)
 | |
|     end
 | |
| 
 | |
|     for i = 1, #components do
 | |
|         local componentId = components[i][1]
 | |
|         for j = 1, #appliedComponents do
 | |
|             local applied = appliedComponents[j]
 | |
|             if applied.component_id == componentId then
 | |
|                 SetPedComponentVariation(cache.ped, componentId, applied.drawable, applied.texture, 2)
 | |
|             end
 | |
|         end
 | |
|     end
 | |
| 
 | |
|     for i = 1, #props do
 | |
|         local propId = props[i][1]
 | |
|         for j = 1, #appliedProps do
 | |
|             local applied = appliedProps[j]
 | |
|             if applied.prop_id == propId then
 | |
|                 SetPedPropIndex(cache.ped, propId, applied.drawable, applied.texture, true)
 | |
|             end
 | |
|         end
 | |
|     end
 | |
| 
 | |
|     TaskPlayAnim(cache.ped, animationsOn.dict, animationsOn.anim, 3.0, 3.0, animationsOn.duration, animationsOn.move, 0, false, false, false)
 | |
| end
 | |
| client.wearClothes = wearClothes
 | |
| 
 | |
| local function removeClothes(typeClothes)
 | |
|     local dataClothes = constants.DATA_CLOTHES[typeClothes]
 | |
|     local animationsOff = dataClothes.animations.off
 | |
|     local components = dataClothes.components[client.getPedDecorationType()]
 | |
|     local props = dataClothes.props[client.getPedDecorationType()]
 | |
| 
 | |
|     RequestAnimDict(animationsOff.dict)
 | |
|     while not HasAnimDictLoaded(animationsOff.dict) do
 | |
|         Wait(0)
 | |
|     end
 | |
| 
 | |
|     for i = 1, #components do
 | |
|         local component = components[i]
 | |
|         SetPedComponentVariation(cache.ped, component[1], component[2], 0, 2)
 | |
|     end
 | |
| 
 | |
|     for i = 1, #props do
 | |
|         ClearPedProp(cache.ped, props[i][1])
 | |
|     end
 | |
| 
 | |
|     TaskPlayAnim(cache.ped, animationsOff.dict, animationsOff.anim, 3.0, 3.0, animationsOff.duration, animationsOff.move, 0, false, false, false)
 | |
| end
 | |
| client.removeClothes = removeClothes
 | |
| 
 | |
| local playerHeading
 | |
| function client.getHeading() return playerHeading end
 | |
| 
 | |
| local callback
 | |
| function client.startPlayerCustomization(cb, conf)
 | |
|     repeat Wait(0) until IsScreenFadedIn() and not IsPlayerTeleportActive() and not IsPlayerSwitchInProgress()
 | |
| 
 | |
|     playerAppearance = client.getPedAppearance(cache.ped)
 | |
|     playerCoords = GetEntityCoords(cache.ped, true)
 | |
|     playerHeading = GetEntityHeading(cache.ped)
 | |
| 
 | |
|     BackupPlayerStats()
 | |
| 
 | |
|     callback = cb
 | |
|     config = conf
 | |
|     reverseCamera = false
 | |
|     isCameraInterpolating = false
 | |
| 
 | |
|     setCamera("default")
 | |
|     SetNuiFocus(true, true)
 | |
|     SetNuiFocusKeepInput(false)
 | |
|     RenderScriptCams(true, false, 0, true, true)
 | |
|     SetEntityInvincible(cache.ped, Config.InvincibleDuringCustomization)
 | |
|     TaskStandStill(cache.ped, -1)
 | |
| 
 | |
|     if Config.HideRadar then DisplayRadar(false) end
 | |
| 
 | |
|     SendNuiMessage(json.encode({
 | |
|         type = "appearance_display",
 | |
|         payload = {
 | |
|             asynchronous = Config.AsynchronousLoading
 | |
|         }
 | |
|     }))
 | |
| end
 | |
| 
 | |
| function client.exitPlayerCustomization(appearance)
 | |
|     RenderScriptCams(false, false, 0, true, true)
 | |
|     DestroyCam(cameraHandle, false)
 | |
|     SetNuiFocus(false, false)
 | |
| 
 | |
|     if Config.HideRadar then DisplayRadar(true) end
 | |
| 
 | |
|     ClearPedTasksImmediately(cache.ped)
 | |
|     SetEntityInvincible(cache.ped, false)
 | |
| 
 | |
|     SendNuiMessage(json.encode({
 | |
|         type = "appearance_hide",
 | |
|         payload = {}
 | |
|     }))
 | |
| 
 | |
|     if not appearance then
 | |
|         client.setPlayerAppearance(getAppearance())
 | |
|     else
 | |
|         client.setPedTattoos(cache.ped, appearance.tattoos)
 | |
|     end
 | |
| 
 | |
|     RestorePlayerStats()
 | |
| 
 | |
|     if callback then
 | |
|         callback(appearance)
 | |
|     end
 | |
| 
 | |
|     callback = nil
 | |
|     config = nil
 | |
|     playerAppearance = nil
 | |
|     playerCoords = nil
 | |
|     cameraHandle = nil
 | |
|     currentCamera = nil
 | |
|     reverseCamera = nil
 | |
|     isCameraInterpolating = nil
 | |
| 
 | |
| end
 | |
| 
 | |
| AddEventHandler("onResourceStop", function(resource)
 | |
|     if resource == GetCurrentResourceName() then
 | |
|         SetNuiFocus(false, false)
 | |
|         SetNuiFocusKeepInput(false)
 | |
|     end
 | |
| end)
 | |
| 
 | |
| exports("startPlayerCustomization", client.startPlayerCustomization)
 | 
