Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
# Deprecated & Discontinued
# LostJ3ster's fork of PainedPsyche's cui_character
## Changes
In this fork I changed the way to load clothing data.
By default PainedPsyche loads the data from GTA itself. Due to an updated Native that does not work anymore.
This fork includes a workaround to
a) load the clothing data from local files (clothingnames/*.json) (default)
b) load the clothing data from [root-cause's v-clothingnames repository](https://github.com/root-cause/v-clothingnames)

Loading the clothing data from local files will reduce the load time a lot, which was requested by [Ciwiel on the cfx forum](https://forum.cfx.re/t/release-cleanui-cui-character/1914841/899)

To change loading style, change Config.UseLocalClothingJSON to false, which will cause the data to be pulled from github, every time the menu opens.

# CleanUI (cui) character
An advanced character and clothes editor that aims to be comfortable to use, hide complexity and blend in with original GTA V interface elements.

Expand Down Expand Up @@ -58,4 +71,4 @@ Clothes customization is sort-of experimental. It relies on pulling entire data

I would be grateful if someone could point out a way to do it better. Preferably one that does not involve including and parsing custom, several megabytes large data files.

Gloves have been omitted entirely from the clothes selection, they are really messy and I have not found a way to automatically match them with other currently selected components. It would require an arduous, manual approach to get them in now.
Gloves have been omitted entirely from the clothes selection, they are really messy and I have not found a way to automatically match them with other currently selected components. It would require an arduous, manual approach to get them in now.
257 changes: 255 additions & 2 deletions client/main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1259,6 +1259,164 @@ function GetPropsData(id)
return result
end

function tablelength(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end

function GetComponentsDataWorkaround(id, cb)
local result = {}

local componentBlacklist = nil

local isMale = GetEntityModel(previewPed) == GetHashKey('mp_m_freemode_01')

if blacklist ~= nil then
if GetEntityModel(previewPed) == GetHashKey('mp_m_freemode_01') then
componentBlacklist = blacklist.components.male
elseif GetEntityModel(previewPed) == GetHashKey('mp_f_freemode_01') then
componentBlacklist = blacklist.components.female
end
end

local allClothes

if Config.UseLocalClothingJSON then
local jsonFile = Config.DefaultClothingLocalPath
if isMale then
jsonFile = jsonFile..Config.DefaultClothing.components.male[id]
else
jsonFile = jsonFile..Config.DefaultClothing.components.female[id]
end

local loadFile= LoadResourceFile(GetCurrentResourceName(), jsonFile)

allClothes = json.decode(loadFile)
else
ESX.TriggerServerCallback('cui_character_workaround:getClothingComponent', function(callback)
allClothes = json.decode(callback)
end, id, isMale)
end

while not allClothes do
Wait(10)
end

local drawableCount = tablelength(allClothes) - 1
for drawable = 0, drawableCount do
local textureCount = tablelength(allClothes[tostring(drawable)]) - 1

for texture = 0, textureCount do
-- only named components
if allClothes[tostring(drawable)][tostring(texture)].Localized ~= 'NULL' then
local blacklisted = false

if componentBlacklist ~= nil then
if componentBlacklist[id] ~= nil then
if componentBlacklist[id][drawable] ~= nil then
if componentBlacklist[id][drawable][texture] ~= nil then
blacklisted = true
end
end
end
end

if not blacklisted then
table.insert(result, {
name = allClothes[tostring(drawable)][tostring(texture)].Localized,
component = id,
drawable = drawable,
texture = texture
})
end
end
end
end

if cb then
cb(result)
else
return result
end
end

function GetPropsDataWorkaround(id, cb)
local result = {}

local propBlacklist = nil

local isMale = GetEntityModel(previewPed) == GetHashKey('mp_m_freemode_01')

if blacklist ~= nil then
if GetEntityModel(previewPed) == GetHashKey('mp_m_freemode_01') then
propBlacklist = blacklist.props.male
elseif GetEntityModel(previewPed) == GetHashKey('mp_f_freemode_01') then
propBlacklist = blacklist.props.female
end
end

local allProps

if Config.UseLocalClothingJSON then
local jsonFile = Config.DefaultClothingLocalPath
if isMale then
jsonFile = jsonFile..Config.DefaultClothing.props.male[id]
else
jsonFile = jsonFile..Config.DefaultClothing.props.female[id]
end

local loadFile= LoadResourceFile(GetCurrentResourceName(), jsonFile)
allProps = json.decode(loadFile)
else
ESX.TriggerServerCallback('cui_character_workaround:getClothingProp', function(callback)
allProps = json.decode(callback)
end, id, isMale)
end

while not allProps do
Wait(10)
end

local drawableCount = tablelength(allProps) - 1

for drawable = 0, drawableCount do
local textureCount = tablelength(allProps[tostring(drawable)]) - 1

for texture = 0, textureCount do
-- only named props
if allProps[tostring(drawable)][tostring(texture)].Localized ~= 'NULL' then
local blacklisted = false

if propBlacklist ~= nil then
if propBlacklist[id] ~= nil then
if propBlacklist[id][drawable] ~= nil then
if propBlacklist[id][drawable][texture] ~= nil then
blacklisted = true
end
end
end
end

if not blacklisted then
table.insert(result, {
name = allProps[tostring(drawable)][tostring(texture)].Localized,
prop = id,
drawable = drawable,
texture = texture
})
end
end
end
end

if cb then
cb(result)
else
return result
end
end

function GetClothesData()
local result = {
topsover = {},
Expand All @@ -1271,6 +1429,7 @@ function GetClothesData()
hats = {},
ears = {},
glasses = {},
arms = {},
lefthands = {},
righthands = {},
}
Expand All @@ -1282,7 +1441,7 @@ function GetClothesData()
-- result.bags = GetComponentsData(5) -- there seems to be no named components in this category
result.masks = GetComponentsData(1)
result.neckarms = GetComponentsData(7) -- chains/ties/suspenders/bangles

result.arms = GetComponentsData(3)
result.hats = GetPropsData(0)
result.ears = GetPropsData(2)
result.glasses = GetPropsData(1)
Expand All @@ -1296,6 +1455,100 @@ function GetClothesData()
mouth (3), left hand (4), righ thand (5), left wrist (6), right wrist (7), hip (8),
left foot(9), right foot (10)
]]

-- Workaround:

local isLoading = 0
if #result.topsover <= 0 then
isLoading = isLoading + 1
GetComponentsDataWorkaround(11, function(data)
result.topsover = data
isLoading = isLoading - 1
end)
end
if #result.topsunder <= 0 then
isLoading = isLoading + 1
GetComponentsDataWorkaround(8, function(data)
result.topsunder = data
isLoading = isLoading - 1
end)
end
if #result.pants <= 0 then
isLoading = isLoading + 1
GetComponentsDataWorkaround(4, function(data)
result.pants = data
isLoading = isLoading - 1
end)
end
if #result.shoes <= 0 then
isLoading = isLoading + 1
GetComponentsDataWorkaround(6, function(data)
result.shoes = data
isLoading = isLoading - 1
end)
end
if #result.masks <= 0 then
isLoading = isLoading + 1
GetComponentsDataWorkaround(1, function(data)
result.masks = data
isLoading = isLoading - 1
end)
end
if #result.neckarms <= 0 then
isLoading = isLoading + 1
GetComponentsDataWorkaround(7, function(data)
result.neckarms = data
isLoading = isLoading - 1
end)
end
if #result.arms <= 0 then
isLoading = isLoading + 1
GetComponentsDataWorkaround(3, function(data)
result.arms = data
isLoading = isLoading - 1
end)
end

if #result.hats <= 0 then
isLoading = isLoading + 1
GetPropsDataWorkaround(0, function(data)
result.hats = data
isLoading = isLoading - 1
end)
end
if #result.ears <= 0 then
isLoading = isLoading + 1
GetPropsDataWorkaround(2, function(data)
result.ears = data
isLoading = isLoading - 1
end)
end
if #result.glasses <= 0 then
isLoading = isLoading + 1
GetPropsDataWorkaround(1, function(data)
result.glasses = data
isLoading = isLoading - 1
end)
end
if #result.lefthands <= 0 then
isLoading = isLoading + 1
GetPropsDataWorkaround(6, function(data)
result.lefthands = data
isLoading = isLoading - 1
end)
end
if #result.righthands <= 0 then
isLoading = isLoading + 1
GetPropsDataWorkaround(7, function(data)
result.righthands = data
isLoading = isLoading - 1
end)
end

while isLoading > 0 do
Wait(10)
end

return result
end

Expand Down Expand Up @@ -1800,7 +2053,7 @@ if Config.EnableESXIdentityIntegration then
LoadCharacter(oldChar, function()
local playerPed = PlayerPedId()
SetPedAoBlobRendering(playerPed, true)
SetEntityAlpha(playerPed, 255)
SetEntityAlpha(playerPed, 0)
end)
currentIdentity = {
firstName = nil,
Expand Down
Loading