Upload files to "client"

This commit is contained in:
tanthius 2026-02-12 11:57:06 +00:00
parent e4c16c876a
commit fd2c6e0051

View File

@ -2,6 +2,7 @@
print("^2[turfwar]^7 appearance.lua loaded (client)") print("^2[turfwar]^7 appearance.lua loaded (client)")
local appearance = nil local appearance = nil
local choosing = false
local function IsFreemodeModel(hash) local function IsFreemodeModel(hash)
return hash == GetHashKey("mp_m_freemode_01") or hash == GetHashKey("mp_f_freemode_01") return hash == GetHashKey("mp_m_freemode_01") or hash == GetHashKey("mp_f_freemode_01")
@ -30,6 +31,74 @@ local function ForcePlayerModel(modelName)
return (GetEntityModel(PlayerPedId()) == model) return (GetEntityModel(PlayerPedId()) == model)
end end
local function ApplyDefaultHeadBlend(ped, gender)
if gender == "f" then
SetPedHeadBlendData(ped,
21, 0, 0,
21, 0, 0,
0.55, 0.0, 0.0,
false
)
else
SetPedHeadBlendData(ped,
0, 0, 0,
0, 0, 0,
0.5, 0.5, 0.0,
false
)
end
for i = 0, 19 do
SetPedFaceFeature(ped, i, 0.0)
end
end
local function clamp(n, a, b)
if n < a then return a end
if n > b then return b end
return n
end
local function SendStateToUI()
if not appearance then return end
SendNUIMessage({
type = "appearance:state",
gender = appearance.gender or "m",
hair_drawable = tonumber(appearance.hair_drawable) or 0,
hair_color = tonumber(appearance.hair_color) or 0
})
end
local function OpenChooser()
if choosing then return end
choosing = true
SetNuiFocus(true, true)
SetNuiFocusKeepInput(true)
SendNUIMessage({ type = "appearance:show" })
SendStateToUI()
-- light input lock so they don't move/shoot while choosing
CreateThread(function()
while choosing do
DisableAllControlActions(0)
-- allow looking around / mouse
EnableControlAction(0, 1, true) -- LookLeftRight
EnableControlAction(0, 2, true) -- LookUpDown
EnableControlAction(0, 239, true) -- Cursor X
EnableControlAction(0, 240, true) -- Cursor Y
Wait(0)
end
end)
end
local function CloseChooser()
if not choosing then return end
choosing = false
SendNUIMessage({ type = "appearance:hide" })
SetNuiFocus(false, false)
SetNuiFocusKeepInput(false)
end
local function ApplyAppearanceNow() local function ApplyAppearanceNow()
if not appearance then return end if not appearance then return end
@ -43,30 +112,9 @@ local function ApplyAppearanceNow()
ped = PlayerPedId() ped = PlayerPedId()
if not ped or ped == 0 then return end if not ped or ped == 0 then return end
end end
local function ApplyDefaultHeadBlend(ped, gender)
if gender == "f" then
-- softer defaults for female
SetPedHeadBlendData(ped,
21, 0, 0, -- shape (mother-ish)
21, 0, 0, -- skin
0.55, 0.0, 0.0,
false
)
else
SetPedHeadBlendData(ped,
0, 0, 0,
0, 0, 0,
0.5, 0.5, 0.0,
false
)
end
-- neutralize extreme face features (optional)
for i = 0, 19 do
SetPedFaceFeature(ped, i, 0.0)
end
end
ApplyDefaultHeadBlend(ped, appearance.gender) ApplyDefaultHeadBlend(ped, appearance.gender)
-- 2) Ensure freemode -- 2) Ensure freemode
if not IsFreemodeModel(GetEntityModel(ped)) then if not IsFreemodeModel(GetEntityModel(ped)) then
print("^1[turfwar]^7 ApplyAppearanceNow: not freemode even after force (something else is overriding model).") print("^1[turfwar]^7 ApplyAppearanceNow: not freemode even after force (something else is overriding model).")
@ -79,13 +127,11 @@ end
local maxHair = GetNumberOfPedDrawableVariations(ped, 2) local maxHair = GetNumberOfPedDrawableVariations(ped, 2)
if maxHair > 0 then if maxHair > 0 then
if hairDrawable < 0 then hairDrawable = 0 end hairDrawable = clamp(hairDrawable, 0, maxHair - 1)
if hairDrawable >= maxHair then hairDrawable = maxHair - 1 end
local maxTex = GetNumberOfPedTextureVariations(ped, 2, hairDrawable) local maxTex = GetNumberOfPedTextureVariations(ped, 2, hairDrawable)
if maxTex <= 0 then maxTex = 1 end if maxTex <= 0 then maxTex = 1 end
if hairTexture < 0 then hairTexture = 0 end hairTexture = clamp(hairTexture, 0, maxTex - 1)
if hairTexture >= maxTex then hairTexture = maxTex - 1 end
SetPedComponentVariation(ped, 2, hairDrawable, hairTexture, 0) SetPedComponentVariation(ped, 2, hairDrawable, hairTexture, 0)
end end
@ -97,12 +143,11 @@ end
local numColors = GetNumHairColors() local numColors = GetNumHairColors()
if numColors and numColors > 0 then if numColors and numColors > 0 then
c = math.max(0, math.min(c, numColors - 1)) c = clamp(c, 0, numColors - 1)
h = math.max(0, math.min(h, numColors - 1)) h = clamp(h, 0, numColors - 1)
else else
-- fallback clamp c = clamp(c, 0, 63)
c = math.max(0, math.min(c, 63)) h = clamp(h, 0, 63)
h = math.max(0, math.min(h, 63))
end end
SetPedHairColor(ped, c, h) SetPedHairColor(ped, c, h)
@ -110,13 +155,22 @@ end
print(("[turfwar] appearance applied: gender=%s hair=%d/%d color=%d/%d") print(("[turfwar] appearance applied: gender=%s hair=%d/%d color=%d/%d")
:format(tostring(appearance.gender), hairDrawable, hairTexture, c, h)) :format(tostring(appearance.gender), hairDrawable, hairTexture, c, h))
-- Tell main.lua (optional) that appearance has been applied
TriggerEvent("turfwar:appearance:applied") TriggerEvent("turfwar:appearance:applied")
end end
RegisterNetEvent("turfwar:appearance:update", function(row) RegisterNetEvent("turfwar:appearance:update", function(row)
appearance = row appearance = row
ApplyAppearanceNow() ApplyAppearanceNow()
-- If server says this was a fresh insert, open chooser
if row and row.isNew then
OpenChooser()
end
-- Keep UI numbers in sync while choosing
if choosing then
SendStateToUI()
end
end) end)
-- Request on resource start & spawn -- Request on resource start & spawn
@ -135,67 +189,83 @@ AddEventHandler("playerSpawned", function()
end) end)
end) end)
-- Commands -- =========================
RegisterCommand("tw_gender", function(_, args) -- NUI callbacks
local g = args[1] and args[1]:lower() or "" -- =========================
if g ~= "m" and g ~= "f" then RegisterNUICallback("appearance:setGender", function(data, cb)
print("^3[turfwar]^7 Usage: /tw_gender m OR /tw_gender f") local g = (data and data.gender) or "m"
return if g ~= "m" and g ~= "f" then g = "m" end
end
TriggerServerEvent("turfwar:appearance:setGender", g) TriggerServerEvent("turfwar:appearance:setGender", g)
end, false) cb({ ok = true })
end)
RegisterCommand("tw_hair_next", function() RegisterNUICallback("appearance:hairNext", function(_, cb)
if not appearance then return end if not appearance then cb({ ok=false }) return end
local ped = PlayerPedId() local ped = PlayerPedId()
if ped == 0 then return end if ped == 0 then cb({ ok=false }) return end
local maxHair = GetNumberOfPedDrawableVariations(ped, 2) local maxHair = GetNumberOfPedDrawableVariations(ped, 2)
if maxHair <= 0 then if maxHair <= 0 then cb({ ok=false }) return end
print("^1[turfwar]^7 No hair variations on this model.")
return
end
local cur = GetPedDrawableVariation(ped, 2) local cur = GetPedDrawableVariation(ped, 2)
local nxt = (cur + 1) % maxHair local nxt = (cur + 1) % maxHair
local maxTex = GetNumberOfPedTextureVariations(ped, 2, nxt)
if maxTex <= 0 then maxTex = 1 end
local tex = 0 TriggerServerEvent("turfwar:appearance:setHair", nxt, 0, appearance.hair_color, appearance.hair_highlight)
TriggerServerEvent("turfwar:appearance:setHair", nxt, tex, appearance.hair_color, appearance.hair_highlight) cb({ ok = true })
end, false) end)
RegisterCommand("tw_hair_prev", function() RegisterNUICallback("appearance:hairPrev", function(_, cb)
if not appearance then return end if not appearance then cb({ ok=false }) return end
local ped = PlayerPedId() local ped = PlayerPedId()
if ped == 0 then return end if ped == 0 then cb({ ok=false }) return end
local maxHair = GetNumberOfPedDrawableVariations(ped, 2) local maxHair = GetNumberOfPedDrawableVariations(ped, 2)
if maxHair <= 0 then return end if maxHair <= 0 then cb({ ok=false }) return end
local cur = GetPedDrawableVariation(ped, 2) local cur = GetPedDrawableVariation(ped, 2)
local prv = (cur - 1) local prv = cur - 1
if prv < 0 then prv = maxHair - 1 end if prv < 0 then prv = maxHair - 1 end
TriggerServerEvent("turfwar:appearance:setHair", prv, 0, appearance.hair_color, appearance.hair_highlight) TriggerServerEvent("turfwar:appearance:setHair", prv, 0, appearance.hair_color, appearance.hair_highlight)
end, false) cb({ ok = true })
end)
RegisterCommand("tw_haircolor", function(_, args) RegisterNUICallback("appearance:colorNext", function(_, cb)
if not appearance then return end if not appearance then cb({ ok=false }) return end
local c = tonumber(args[1])
local h = tonumber(args[2])
if c == nil then
print("^3[turfwar]^7 Usage: /tw_haircolor <color> [highlight]")
return
end
if h == nil then h = c end
TriggerServerEvent("turfwar:appearance:setHair", appearance.hair_drawable, appearance.hair_texture, c, h)
end, false)
RegisterCommand("tw_appearance", function() local num = GetNumHairColors()
print("^3[turfwar]^7 Commands:") if not num or num <= 0 then num = 64 end
print("^3[turfwar]^7 /tw_gender m|f")
print("^3[turfwar]^7 /tw_hair_next (cycle)") local c = tonumber(appearance.hair_color) or 0
print("^3[turfwar]^7 /tw_hair_prev (cycle)") c = (c + 1) % num
print("^3[turfwar]^7 /tw_haircolor <color> [highlight]")
TriggerServerEvent("turfwar:appearance:setHair", appearance.hair_drawable, appearance.hair_texture, c, c)
cb({ ok = true })
end)
RegisterNUICallback("appearance:colorPrev", function(_, cb)
if not appearance then cb({ ok=false }) return end
local num = GetNumHairColors()
if not num or num <= 0 then num = 64 end
local c = tonumber(appearance.hair_color) or 0
c = c - 1
if c < 0 then c = num - 1 end
TriggerServerEvent("turfwar:appearance:setHair", appearance.hair_drawable, appearance.hair_texture, c, c)
cb({ ok = true })
end)
RegisterNUICallback("appearance:save", function(_, cb)
-- Nothing special needed: we already write to DB on every click
CloseChooser()
cb({ ok = true })
end)
-- =========================
-- Keep your commands too (optional)
-- =========================
RegisterCommand("tw_appearance_ui", function()
OpenChooser()
end, false) end, false)