Part 2
85
resources/[il]/illenium-appearance/client/blips.lua
Normal file
@ -0,0 +1,85 @@
|
||||
local Blips = {}
|
||||
local client = client
|
||||
|
||||
local function ShowBlip(blipConfig, blip)
|
||||
if blip.job and blip.job ~= client.job.name then
|
||||
return false
|
||||
elseif blip.gang and blip.gang ~= client.gang.name then
|
||||
return false
|
||||
end
|
||||
|
||||
if Config.RCoreTattoosCompatibility and blip.type == "tattoo" then
|
||||
return false
|
||||
end
|
||||
|
||||
return (blipConfig.Show and blip.showBlip == nil) or blip.showBlip
|
||||
end
|
||||
|
||||
local function CreateBlip(blipConfig, coords)
|
||||
local blip = AddBlipForCoord(coords.x, coords.y, coords.z)
|
||||
SetBlipSprite(blip, blipConfig.Sprite)
|
||||
SetBlipColour(blip, blipConfig.Color)
|
||||
SetBlipScale(blip, blipConfig.Scale)
|
||||
SetBlipAsShortRange(blip, true)
|
||||
BeginTextCommandSetBlipName("STRING")
|
||||
AddTextComponentString(blipConfig.Name)
|
||||
EndTextCommandSetBlipName(blip)
|
||||
return blip
|
||||
end
|
||||
|
||||
local function SetupBlips()
|
||||
for k, _ in pairs(Config.Stores) do
|
||||
local blipConfig = Config.Blips[Config.Stores[k].type]
|
||||
if ShowBlip(blipConfig, Config.Stores[k]) then
|
||||
local blip = CreateBlip(blipConfig, Config.Stores[k].coords)
|
||||
Blips[#Blips + 1] = blip
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ResetBlips()
|
||||
if Config.ShowNearestShopOnly then
|
||||
return
|
||||
end
|
||||
|
||||
for i = 1, #Blips do
|
||||
RemoveBlip(Blips[i])
|
||||
end
|
||||
Blips = {}
|
||||
SetupBlips()
|
||||
end
|
||||
|
||||
local function ShowNearestShopBlip()
|
||||
for k in pairs(Config.Blips) do
|
||||
Blips[k] = 0
|
||||
end
|
||||
while true do
|
||||
local coords = GetEntityCoords(cache.ped)
|
||||
for shopType, blipConfig in pairs(Config.Blips) do
|
||||
local closest = 1000000
|
||||
local closestCoords
|
||||
|
||||
for _, shop in pairs(Config.Stores) do
|
||||
if shop.type == shopType and ShowBlip(blipConfig, shop) then
|
||||
local dist = #(coords - vector3(shop.coords.xyz))
|
||||
if dist < closest then
|
||||
closest = dist
|
||||
closestCoords = shop.coords
|
||||
end
|
||||
end
|
||||
end
|
||||
if DoesBlipExist(Blips[shopType]) then
|
||||
RemoveBlip(Blips[shopType])
|
||||
end
|
||||
|
||||
if closestCoords then
|
||||
Blips[shopType] = CreateBlip(blipConfig, closestCoords)
|
||||
end
|
||||
end
|
||||
Wait(Config.NearestShopBlipUpdateDelay)
|
||||
end
|
||||
end
|
||||
|
||||
if Config.ShowNearestShopOnly then
|
||||
CreateThread(ShowNearestShopBlip)
|
||||
end
|
756
resources/[il]/illenium-appearance/client/client.lua
Normal file
@ -0,0 +1,756 @@
|
||||
local client = client
|
||||
local reloadSkinTimer = GetGameTimer()
|
||||
|
||||
local function LoadPlayerUniform(reset)
|
||||
if reset then
|
||||
TriggerServerEvent("illenium-appearance:server:syncUniform", nil)
|
||||
return
|
||||
end
|
||||
lib.callback("illenium-appearance:server:getUniform", false, function(uniformData)
|
||||
if not uniformData then
|
||||
return
|
||||
end
|
||||
if Config.BossManagedOutfits then
|
||||
local result = lib.callback.await("illenium-appearance:server:getManagementOutfits", false, uniformData.type, Framework.GetGender())
|
||||
local uniform = nil
|
||||
for i = 1, #result, 1 do
|
||||
if result[i].name == uniformData.name then
|
||||
uniform = {
|
||||
type = uniformData.type,
|
||||
name = result[i].name,
|
||||
model = result[i].model,
|
||||
components = result[i].components,
|
||||
props = result[i].props,
|
||||
disableSave = true,
|
||||
}
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not uniform then
|
||||
TriggerServerEvent("illenium-appearance:server:syncUniform", nil) -- Uniform doesn't exist anymore
|
||||
return
|
||||
end
|
||||
|
||||
TriggerEvent("illenium-appearance:client:changeOutfit", uniform)
|
||||
else
|
||||
local outfits = Config.Outfits[uniformData.jobName][uniformData.gender]
|
||||
local uniform = nil
|
||||
for i = 1, #outfits, 1 do
|
||||
if outfits[i].name == uniformData.label then
|
||||
uniform = outfits[i]
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not uniform then
|
||||
TriggerServerEvent("illenium-appearance:server:syncUniform", nil) -- Uniform doesn't exist anymore
|
||||
return
|
||||
end
|
||||
|
||||
uniform.jobName = uniformData.jobName
|
||||
uniform.gender = uniformData.gender
|
||||
|
||||
TriggerEvent("illenium-appearance:client:loadJobOutfit", uniform)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function InitAppearance()
|
||||
Framework.UpdatePlayerData()
|
||||
lib.callback("illenium-appearance:server:getAppearance", false, function(appearance)
|
||||
if not appearance then
|
||||
return
|
||||
end
|
||||
|
||||
client.setPlayerAppearance(appearance)
|
||||
if Config.PersistUniforms then
|
||||
LoadPlayerUniform()
|
||||
end
|
||||
end)
|
||||
ResetBlips()
|
||||
if Config.BossManagedOutfits then
|
||||
Management.AddItems()
|
||||
end
|
||||
RestorePlayerStats()
|
||||
end
|
||||
|
||||
AddEventHandler("onResourceStart", function(resource)
|
||||
if resource == GetCurrentResourceName() then
|
||||
InitAppearance()
|
||||
end
|
||||
end)
|
||||
|
||||
local function getNewCharacterConfig()
|
||||
local config = GetDefaultConfig()
|
||||
config.enableExit = false
|
||||
|
||||
config.ped = Config.NewCharacterSections.Ped
|
||||
config.headBlend = Config.NewCharacterSections.HeadBlend
|
||||
config.faceFeatures = Config.NewCharacterSections.FaceFeatures
|
||||
config.headOverlays = Config.NewCharacterSections.HeadOverlays
|
||||
config.components = Config.NewCharacterSections.Components
|
||||
config.props = Config.NewCharacterSections.Props
|
||||
config.tattoos = not Config.RCoreTattoosCompatibility and Config.NewCharacterSections.Tattoos
|
||||
|
||||
return config
|
||||
end
|
||||
|
||||
function SetInitialClothes(initial)
|
||||
client.setPlayerModel(initial.Model)
|
||||
-- Fix for tattoo's appearing when creating a new character
|
||||
local ped = cache.ped
|
||||
client.setPedTattoos(ped, {})
|
||||
client.setPedComponents(ped, initial.Components)
|
||||
client.setPedProps(ped, initial.Props)
|
||||
client.setPedHair(ped, initial.Hair, {})
|
||||
ClearPedDecorations(ped)
|
||||
end
|
||||
|
||||
function InitializeCharacter(gender, onSubmit, onCancel)
|
||||
SetInitialClothes(Config.InitialPlayerClothes[gender])
|
||||
local config = getNewCharacterConfig()
|
||||
TriggerServerEvent("illenium-appearance:server:ChangeRoutingBucket")
|
||||
client.startPlayerCustomization(function(appearance)
|
||||
if (appearance) then
|
||||
TriggerServerEvent("illenium-appearance:server:saveAppearance", appearance)
|
||||
if onSubmit then
|
||||
onSubmit()
|
||||
end
|
||||
elseif onCancel then
|
||||
onCancel()
|
||||
end
|
||||
Framework.CachePed()
|
||||
TriggerServerEvent("illenium-appearance:server:ResetRoutingBucket")
|
||||
end, config)
|
||||
end
|
||||
|
||||
function OpenShop(config, isPedMenu, shopType)
|
||||
lib.callback("illenium-appearance:server:hasMoney", false, function(hasMoney, money)
|
||||
if not hasMoney and not isPedMenu then
|
||||
lib.notify({
|
||||
title = "Cannot Enter Shop",
|
||||
description = "Not enough cash. Need $" .. money,
|
||||
type = "error",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
client.startPlayerCustomization(function(appearance)
|
||||
if appearance then
|
||||
if not isPedMenu then
|
||||
TriggerServerEvent("illenium-appearance:server:chargeCustomer", shopType)
|
||||
end
|
||||
TriggerServerEvent("illenium-appearance:server:saveAppearance", appearance)
|
||||
else
|
||||
lib.notify({
|
||||
title = _L("cancelled.title"),
|
||||
description = _L("cancelled.description"),
|
||||
type = "inform",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
end
|
||||
Framework.CachePed()
|
||||
end, config)
|
||||
end, shopType)
|
||||
end
|
||||
|
||||
local function OpenClothingShop(isPedMenu)
|
||||
local config = GetDefaultConfig()
|
||||
config.components = true
|
||||
config.props = true
|
||||
|
||||
if isPedMenu then
|
||||
config.ped = true
|
||||
config.headBlend = true
|
||||
config.faceFeatures = true
|
||||
config.headOverlays = true
|
||||
config.tattoos = not Config.RCoreTattoosCompatibility and true
|
||||
end
|
||||
OpenShop(config, isPedMenu, "clothing")
|
||||
end
|
||||
|
||||
RegisterNetEvent("illenium-appearance:client:openClothingShop", OpenClothingShop)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:client:importOutfitCode", function()
|
||||
local response = lib.inputDialog(_L("outfits.import.title"), {
|
||||
{
|
||||
type = "input",
|
||||
label = _L("outfits.import.name.label"),
|
||||
placeholder = _L("outfits.import.name.placeholder"),
|
||||
default = _L("outfits.import.name.default"),
|
||||
required = true
|
||||
},
|
||||
{
|
||||
type = "input",
|
||||
label = _L("outfits.import.code.label"),
|
||||
placeholder = "XXXXXXXXXXXX",
|
||||
required = true
|
||||
}
|
||||
})
|
||||
|
||||
if not response then
|
||||
return
|
||||
end
|
||||
|
||||
local outfitName = response[1]
|
||||
local outfitCode = response[2]
|
||||
if outfitCode ~= nil then
|
||||
Wait(500)
|
||||
lib.callback("illenium-appearance:server:importOutfitCode", false, function(success)
|
||||
if success then
|
||||
lib.notify({
|
||||
title = _L("outfits.import.success.title"),
|
||||
description = _L("outfits.import.success.description"),
|
||||
type = "success",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
else
|
||||
lib.notify({
|
||||
title = _L("outfits.import.failure.title"),
|
||||
description = _L("outfits.import.failure.description"),
|
||||
type = "error",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
end
|
||||
end, outfitName, outfitCode)
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:client:generateOutfitCode", function(id)
|
||||
lib.callback("illenium-appearance:server:generateOutfitCode", false, function(code)
|
||||
if not code then
|
||||
lib.notify({
|
||||
title = _L("outfits.generate.failure.title"),
|
||||
description = _L("outfits.generate.failure.description"),
|
||||
type = "error",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
return
|
||||
end
|
||||
lib.setClipboard(code)
|
||||
lib.inputDialog(_L("outfits.generate.success.title"), {
|
||||
{
|
||||
type = "input",
|
||||
label = _L("outfits.generate.success.description"),
|
||||
default = code,
|
||||
disabled = true
|
||||
}
|
||||
})
|
||||
end, id)
|
||||
end)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:client:saveOutfit", function()
|
||||
local response = lib.inputDialog(_L("outfits.save.title"), {
|
||||
{
|
||||
type = "input",
|
||||
label = _L("outfits.save.name.label"),
|
||||
placeholder = _L("outfits.save.name.placeholder"),
|
||||
required = true
|
||||
}
|
||||
})
|
||||
|
||||
if not response then
|
||||
return
|
||||
end
|
||||
|
||||
local outfitName = response[1]
|
||||
if outfitName then
|
||||
Wait(500)
|
||||
lib.callback("illenium-appearance:server:getOutfits", false, function(outfits)
|
||||
local outfitExists = false
|
||||
for i = 1, #outfits, 1 do
|
||||
if outfits[i].name:lower() == outfitName:lower() then
|
||||
outfitExists = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if outfitExists then
|
||||
lib.notify({
|
||||
title = _L("outfits.save.failure.title"),
|
||||
description = _L("outfits.save.failure.description"),
|
||||
type = "error",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
local pedModel = client.getPedModel(cache.ped)
|
||||
local pedComponents = client.getPedComponents(cache.ped)
|
||||
local pedProps = client.getPedProps(cache.ped)
|
||||
|
||||
TriggerServerEvent("illenium-appearance:server:saveOutfit", outfitName, pedModel, pedComponents, pedProps)
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent('illenium-appearance:client:updateOutfit', function(outfitID)
|
||||
if not outfitID then return end
|
||||
|
||||
lib.callback("illenium-appearance:server:getOutfits", false, function(outfits)
|
||||
local outfitExists = false
|
||||
for i = 1, #outfits, 1 do
|
||||
if outfits[i].id == outfitID then
|
||||
outfitExists = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not outfitExists then
|
||||
lib.notify({
|
||||
title = _L("outfits.update.failure.title"),
|
||||
description = _L("outfits.update.failure.description"),
|
||||
type = "error",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
local pedModel = client.getPedModel(cache.ped)
|
||||
local pedComponents = client.getPedComponents(cache.ped)
|
||||
local pedProps = client.getPedProps(cache.ped)
|
||||
|
||||
TriggerServerEvent("illenium-appearance:server:updateOutfit", outfitID, pedModel, pedComponents, pedProps)
|
||||
end)
|
||||
end)
|
||||
|
||||
local function RegisterChangeOutfitMenu(id, parent, outfits, mType)
|
||||
local changeOutfitMenu = {
|
||||
id = id,
|
||||
title = _L("outfits.change.title"),
|
||||
menu = parent,
|
||||
options = {}
|
||||
}
|
||||
for i = 1, #outfits, 1 do
|
||||
changeOutfitMenu.options[#changeOutfitMenu.options + 1] = {
|
||||
title = outfits[i].name,
|
||||
description = outfits[i].model,
|
||||
event = "illenium-appearance:client:changeOutfit",
|
||||
args = {
|
||||
type = mType,
|
||||
name = outfits[i].name,
|
||||
model = outfits[i].model,
|
||||
components = outfits[i].components,
|
||||
props = outfits[i].props,
|
||||
disableSave = mType and true or false
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
table.sort(changeOutfitMenu.options, function(a, b)
|
||||
return a.title < b.title
|
||||
end)
|
||||
|
||||
lib.registerContext(changeOutfitMenu)
|
||||
end
|
||||
|
||||
local function RegisterUpdateOutfitMenu(id, parent, outfits)
|
||||
local updateOutfitMenu = {
|
||||
id = id,
|
||||
title = _L("outfits.update.title"),
|
||||
menu = parent,
|
||||
options = {}
|
||||
}
|
||||
for i = 1, #outfits, 1 do
|
||||
updateOutfitMenu.options[#updateOutfitMenu.options + 1] = {
|
||||
title = outfits[i].name,
|
||||
description = outfits[i].model,
|
||||
event = "illenium-appearance:client:updateOutfit",
|
||||
args = outfits[i].id
|
||||
}
|
||||
end
|
||||
|
||||
table.sort(updateOutfitMenu.options, function(a, b)
|
||||
return a.title < b.title
|
||||
end)
|
||||
|
||||
lib.registerContext(updateOutfitMenu)
|
||||
end
|
||||
|
||||
local function RegisterGenerateOutfitCodeMenu(id, parent, outfits)
|
||||
local generateOutfitCodeMenu = {
|
||||
id = id,
|
||||
title = _L("outfits.generate.title"),
|
||||
menu = parent,
|
||||
options = {}
|
||||
}
|
||||
for i = 1, #outfits, 1 do
|
||||
generateOutfitCodeMenu.options[#generateOutfitCodeMenu.options + 1] = {
|
||||
title = outfits[i].name,
|
||||
description = outfits[i].model,
|
||||
event = "illenium-appearance:client:generateOutfitCode",
|
||||
args = outfits[i].id
|
||||
}
|
||||
end
|
||||
|
||||
lib.registerContext(generateOutfitCodeMenu)
|
||||
end
|
||||
|
||||
local function RegisterDeleteOutfitMenu(id, parent, outfits, deleteEvent)
|
||||
local deleteOutfitMenu = {
|
||||
id = id,
|
||||
title = _L("outfits.delete.title"),
|
||||
menu = parent,
|
||||
options = {}
|
||||
}
|
||||
|
||||
table.sort(outfits, function(a, b)
|
||||
return a.name < b.name
|
||||
end)
|
||||
|
||||
for i = 1, #outfits, 1 do
|
||||
deleteOutfitMenu.options[#deleteOutfitMenu.options + 1] = {
|
||||
title = string.format(_L("outfits.delete.item.title"), outfits[i].name),
|
||||
description = string.format(_L("outfits.delete.item.description"), outfits[i].model, (outfits[i].gender and (" - Gender: " .. outfits[i].gender) or "")),
|
||||
event = deleteEvent,
|
||||
args = outfits[i].id
|
||||
}
|
||||
end
|
||||
|
||||
lib.registerContext(deleteOutfitMenu)
|
||||
end
|
||||
|
||||
RegisterNetEvent("illenium-appearance:client:OutfitManagementMenu", function(args)
|
||||
local outfits = lib.callback.await("illenium-appearance:server:getManagementOutfits", false, args.type, Framework.GetGender())
|
||||
local managementMenuID = "illenium_appearance_outfit_management_menu"
|
||||
local changeManagementOutfitMenuID = "illenium_appearance_change_management_outfit_menu"
|
||||
local deleteManagementOutfitMenuID = "illenium_appearance_delete_management_outfit_menu"
|
||||
|
||||
RegisterChangeOutfitMenu(changeManagementOutfitMenuID, managementMenuID, outfits, args.type)
|
||||
RegisterDeleteOutfitMenu(deleteManagementOutfitMenuID, managementMenuID, outfits, "illenium-appearance:client:DeleteManagementOutfit")
|
||||
local managementMenu = {
|
||||
id = managementMenuID,
|
||||
title = string.format(_L("outfits.manage.title"), args.type),
|
||||
options = {
|
||||
{
|
||||
title = _L("outfits.change.title"),
|
||||
description = string.format(_L("outfits.change.description"), args.type),
|
||||
menu = changeManagementOutfitMenuID,
|
||||
},
|
||||
{
|
||||
title = _L("outfits.save.menuTitle"),
|
||||
description = string.format(_L("outfits.save.menuDescription"), args.type),
|
||||
event = "illenium-appearance:client:SaveManagementOutfit",
|
||||
args = args.type
|
||||
},
|
||||
{
|
||||
title = _L("outfits.delete.title"),
|
||||
description = string.format(_L("outfits.delete.description"), args.type),
|
||||
menu = deleteManagementOutfitMenuID,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Management.AddBackMenuItem(managementMenu, args)
|
||||
|
||||
lib.registerContext(managementMenu)
|
||||
lib.showContext(managementMenuID)
|
||||
end)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:client:SaveManagementOutfit", function(mType)
|
||||
local outfitData = {
|
||||
Type = mType,
|
||||
Model = client.getPedModel(cache.ped),
|
||||
Components = client.getPedComponents(cache.ped),
|
||||
Props = client.getPedProps(cache.ped)
|
||||
}
|
||||
|
||||
local rankValues
|
||||
|
||||
if mType == "Job" then
|
||||
outfitData.JobName = client.job.name
|
||||
rankValues = Framework.GetRankInputValues("job")
|
||||
|
||||
else
|
||||
outfitData.JobName = client.gang.name
|
||||
rankValues = Framework.GetRankInputValues("gang")
|
||||
end
|
||||
|
||||
local dialogResponse = lib.inputDialog(_L("outfits.save.managementTitle"), {
|
||||
{
|
||||
label = _L("outfits.save.name.label"),
|
||||
type = "input",
|
||||
required = true
|
||||
},
|
||||
{
|
||||
label = _L("outfits.save.gender.label"),
|
||||
type = "select",
|
||||
options = {
|
||||
{
|
||||
label = _L("outfits.save.gender.male"), value = "male"
|
||||
},
|
||||
{
|
||||
label = _L("outfits.save.gender.female"), value = "female"
|
||||
}
|
||||
},
|
||||
default = "male",
|
||||
},
|
||||
{
|
||||
label = _L("outfits.save.rank.label"),
|
||||
type = "select",
|
||||
options = rankValues,
|
||||
default = "0"
|
||||
}
|
||||
})
|
||||
|
||||
if not dialogResponse then
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
outfitData.Name = dialogResponse[1]
|
||||
outfitData.Gender = dialogResponse[2]
|
||||
outfitData.MinRank = tonumber(dialogResponse[3])
|
||||
|
||||
TriggerServerEvent("illenium-appearance:server:saveManagementOutfit", outfitData)
|
||||
|
||||
end)
|
||||
|
||||
local function RegisterWorkOutfitsListMenu(id, parent, menuData)
|
||||
local menu = {
|
||||
id = id,
|
||||
menu = parent,
|
||||
title = _L("jobOutfits.title"),
|
||||
options = {}
|
||||
}
|
||||
local event = "illenium-appearance:client:loadJobOutfit"
|
||||
if Config.BossManagedOutfits then
|
||||
event = "illenium-appearance:client:changeOutfit"
|
||||
end
|
||||
if menuData then
|
||||
for _, v in pairs(menuData) do
|
||||
menu.options[#menu.options + 1] = {
|
||||
title = v.name,
|
||||
event = event,
|
||||
args = v
|
||||
}
|
||||
end
|
||||
end
|
||||
lib.registerContext(menu)
|
||||
end
|
||||
|
||||
function OpenMenu(isPedMenu, menuType, menuData)
|
||||
local mainMenuID = "illenium_appearance_main_menu"
|
||||
local mainMenu = {
|
||||
id = mainMenuID
|
||||
}
|
||||
local menuItems = {}
|
||||
|
||||
local outfits = lib.callback.await("illenium-appearance:server:getOutfits", false)
|
||||
local changeOutfitMenuID = "illenium_appearance_change_outfit_menu"
|
||||
local updateOutfitMenuID = "illenium_appearance_update_outfit_menu"
|
||||
local deleteOutfitMenuID = "illenium_appearance_delete_outfit_menu"
|
||||
local generateOutfitCodeMenuID = "illenium_appearance_generate_outfit_code_menu"
|
||||
|
||||
RegisterChangeOutfitMenu(changeOutfitMenuID, mainMenuID, outfits)
|
||||
RegisterUpdateOutfitMenu(updateOutfitMenuID, mainMenuID, outfits)
|
||||
RegisterDeleteOutfitMenu(deleteOutfitMenuID, mainMenuID, outfits, "illenium-appearance:client:deleteOutfit")
|
||||
RegisterGenerateOutfitCodeMenu(generateOutfitCodeMenuID, mainMenuID, outfits)
|
||||
local outfitMenuItems = {
|
||||
{
|
||||
title = _L("outfits.change.title"),
|
||||
description = _L("outfits.change.pDescription"),
|
||||
menu = changeOutfitMenuID
|
||||
},
|
||||
{
|
||||
title = _L("outfits.update.title"),
|
||||
description = _L("outfits.update.description"),
|
||||
menu = updateOutfitMenuID
|
||||
},
|
||||
{
|
||||
title = _L("outfits.save.menuTitle"),
|
||||
description = _L("outfits.save.description"),
|
||||
event = "illenium-appearance:client:saveOutfit"
|
||||
},
|
||||
{
|
||||
title = _L("outfits.generate.title"),
|
||||
description = _L("outfits.generate.description"),
|
||||
menu = generateOutfitCodeMenuID
|
||||
},
|
||||
{
|
||||
title = _L("outfits.delete.title"),
|
||||
description = _L("outfits.delete.mDescription"),
|
||||
menu = deleteOutfitMenuID
|
||||
},
|
||||
{
|
||||
title = _L("outfits.import.menuTitle"),
|
||||
description = _L("outfits.import.description"),
|
||||
event = "illenium-appearance:client:importOutfitCode"
|
||||
}
|
||||
}
|
||||
if menuType == "default" then
|
||||
local header = string.format(_L("clothing.title"), Config.ClothingCost)
|
||||
if isPedMenu then
|
||||
header = _L("clothing.titleNoPrice")
|
||||
end
|
||||
mainMenu.title = _L("clothing.options.title")
|
||||
menuItems[#menuItems + 1] = {
|
||||
title = header,
|
||||
description = _L("clothing.options.description"),
|
||||
event = "illenium-appearance:client:openClothingShop",
|
||||
args = isPedMenu
|
||||
}
|
||||
for i = 0, #outfitMenuItems, 1 do
|
||||
menuItems[#menuItems + 1] = outfitMenuItems[i]
|
||||
end
|
||||
elseif menuType == "outfit" then
|
||||
mainMenu.title = _L("clothing.outfits.title")
|
||||
for i = 0, #outfitMenuItems, 1 do
|
||||
menuItems[#menuItems + 1] = outfitMenuItems[i]
|
||||
end
|
||||
elseif menuType == "job-outfit" then
|
||||
mainMenu.title = _L("clothing.outfits.title")
|
||||
menuItems[#menuItems + 1] = {
|
||||
title = _L("clothing.outfits.civilian.title"),
|
||||
description = _L("clothing.outfits.civilian.description"),
|
||||
event = "illenium-appearance:client:reloadSkin",
|
||||
args = true
|
||||
}
|
||||
|
||||
local workOutfitsMenuID = "illenium_appearance_work_outfits_menu"
|
||||
RegisterWorkOutfitsListMenu(workOutfitsMenuID, mainMenuID, menuData)
|
||||
|
||||
menuItems[#menuItems + 1] = {
|
||||
title = _L("jobOutfits.title"),
|
||||
description = _L("jobOutfits.description"),
|
||||
menu = workOutfitsMenuID
|
||||
}
|
||||
end
|
||||
mainMenu.options = menuItems
|
||||
|
||||
lib.registerContext(mainMenu)
|
||||
lib.showContext(mainMenuID)
|
||||
end
|
||||
|
||||
RegisterNetEvent("illenium-appearance:client:openClothingShopMenu", function(isPedMenu)
|
||||
if type(isPedMenu) == "table" then
|
||||
isPedMenu = false
|
||||
end
|
||||
OpenMenu(isPedMenu, "default")
|
||||
end)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:client:OpenBarberShop", OpenBarberShop)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:client:OpenTattooShop", OpenTattooShop)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:client:OpenSurgeonShop", OpenSurgeonShop)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:client:changeOutfit", function(data)
|
||||
local pedModel = client.getPedModel(cache.ped)
|
||||
local appearanceDB
|
||||
if pedModel ~= data.model then
|
||||
local p = promise.new()
|
||||
lib.callback("illenium-appearance:server:getAppearance", false, function(appearance)
|
||||
BackupPlayerStats()
|
||||
if appearance then
|
||||
client.setPlayerAppearance(appearance)
|
||||
RestorePlayerStats()
|
||||
else
|
||||
lib.notify({
|
||||
title = _L("outfits.change.failure.title"),
|
||||
description = _L("outfits.change.failure.description"),
|
||||
type = "error",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
end
|
||||
p:resolve(appearance)
|
||||
end, data.model)
|
||||
appearanceDB = Citizen.Await(p)
|
||||
else
|
||||
appearanceDB = client.getPedAppearance(cache.ped)
|
||||
end
|
||||
if appearanceDB then
|
||||
client.setPedComponents(cache.ped, data.components)
|
||||
client.setPedProps(cache.ped, data.props)
|
||||
client.setPedHair(cache.ped, appearanceDB.hair, appearanceDB.tattoos)
|
||||
|
||||
if data.disableSave then
|
||||
TriggerServerEvent("illenium-appearance:server:syncUniform", {
|
||||
type = data.type,
|
||||
name = data.name
|
||||
}) -- Is a uniform
|
||||
else
|
||||
local appearance = client.getPedAppearance(cache.ped)
|
||||
TriggerServerEvent("illenium-appearance:server:saveAppearance", appearance)
|
||||
end
|
||||
Framework.CachePed()
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:client:DeleteManagementOutfit", function(id)
|
||||
TriggerServerEvent("illenium-appearance:server:deleteManagementOutfit", id)
|
||||
lib.notify({
|
||||
title = _L("outfits.delete.management.success.title"),
|
||||
description = _L("outfits.delete.management.success.description"),
|
||||
type = "success",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
end)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:client:deleteOutfit", function(id)
|
||||
TriggerServerEvent("illenium-appearance:server:deleteOutfit", id)
|
||||
lib.notify({
|
||||
title = _L("outfits.delete.success.title"),
|
||||
description = _L("outfits.delete.success.description"),
|
||||
type = "success",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
end)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:client:openJobOutfitsMenu", function(outfitsToShow)
|
||||
OpenMenu(nil, "job-outfit", outfitsToShow)
|
||||
end)
|
||||
|
||||
local function InCooldown()
|
||||
return (GetGameTimer() - reloadSkinTimer) < Config.ReloadSkinCooldown
|
||||
end
|
||||
|
||||
RegisterNetEvent("illenium-appearance:client:reloadSkin", function(bypassChecks)
|
||||
if not bypassChecks and InCooldown() or Framework.CheckPlayerMeta() or cache.vehicle or IsPedFalling(cache.ped) then
|
||||
lib.notify({
|
||||
title = _L("commands.reloadskin.failure.title"),
|
||||
description = _L("commands.reloadskin.failure.description"),
|
||||
type = "error",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
reloadSkinTimer = GetGameTimer()
|
||||
BackupPlayerStats()
|
||||
|
||||
lib.callback("illenium-appearance:server:getAppearance", false, function(appearance)
|
||||
if not appearance then
|
||||
return
|
||||
end
|
||||
client.setPlayerAppearance(appearance)
|
||||
if Config.PersistUniforms then
|
||||
LoadPlayerUniform(bypassChecks)
|
||||
end
|
||||
RestorePlayerStats()
|
||||
end)
|
||||
end)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:client:ClearStuckProps", function()
|
||||
if InCooldown() or Framework.CheckPlayerMeta() then
|
||||
lib.notify({
|
||||
title = _L("commands.clearstuckprops.failure.title"),
|
||||
description = _L("commands.clearstuckprops.failure.description"),
|
||||
type = "error",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
reloadSkinTimer = GetGameTimer()
|
||||
|
||||
for _, v in pairs(GetGamePool("CObject")) do
|
||||
if IsEntityAttachedToEntity(cache.ped, v) then
|
||||
SetEntityAsMissionEntity(v, true, true)
|
||||
DeleteObject(v)
|
||||
DeleteEntity(v)
|
||||
end
|
||||
end
|
||||
end)
|
83
resources/[il]/illenium-appearance/client/common.lua
Normal file
@ -0,0 +1,83 @@
|
||||
function CheckDuty()
|
||||
return not Config.OnDutyOnlyClothingRooms or (Config.OnDutyOnlyClothingRooms and client.job.onduty)
|
||||
end
|
||||
|
||||
function IsPlayerAllowedForOutfitRoom(outfitRoom)
|
||||
local isAllowed = false
|
||||
local count = #outfitRoom.citizenIDs
|
||||
for i = 1, count, 1 do
|
||||
if Framework.IsPlayerAllowed(outfitRoom.citizenIDs[i]) then
|
||||
isAllowed = true
|
||||
break
|
||||
end
|
||||
end
|
||||
return isAllowed or not outfitRoom.citizenIDs or count == 0
|
||||
end
|
||||
|
||||
function GetPlayerJobOutfits(job)
|
||||
local outfits = {}
|
||||
local gender = Framework.GetGender()
|
||||
local gradeLevel = job and Framework.GetJobGrade() or Framework.GetGangGrade()
|
||||
local jobName = job and client.job.name or client.gang.name
|
||||
|
||||
if Config.BossManagedOutfits then
|
||||
local mType = job and "Job" or "Gang"
|
||||
local result = lib.callback.await("illenium-appearance:server:getManagementOutfits", false, mType, gender)
|
||||
for i = 1, #result, 1 do
|
||||
outfits[#outfits + 1] = {
|
||||
type = mType,
|
||||
model = result[i].model,
|
||||
components = result[i].components,
|
||||
props = result[i].props,
|
||||
disableSave = true,
|
||||
name = result[i].name
|
||||
}
|
||||
end
|
||||
elseif Config.Outfits[jobName] and Config.Outfits[jobName][gender] then
|
||||
for i = 1, #Config.Outfits[jobName][gender], 1 do
|
||||
for _, v in pairs(Config.Outfits[jobName][gender][i].grades) do
|
||||
if v == gradeLevel then
|
||||
outfits[#outfits + 1] = Config.Outfits[jobName][gender][i]
|
||||
outfits[#outfits].gender = gender
|
||||
outfits[#outfits].jobName = jobName
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return outfits
|
||||
end
|
||||
|
||||
function OpenOutfitRoom(outfitRoom)
|
||||
local isAllowed = IsPlayerAllowedForOutfitRoom(outfitRoom)
|
||||
if isAllowed then
|
||||
OpenMenu(nil, "outfit")
|
||||
end
|
||||
end
|
||||
|
||||
function OpenBarberShop()
|
||||
local config = GetDefaultConfig()
|
||||
config.headOverlays = true
|
||||
OpenShop(config, false, "barber")
|
||||
end
|
||||
|
||||
function OpenTattooShop()
|
||||
local config = GetDefaultConfig()
|
||||
config.tattoos = true
|
||||
OpenShop(config, false, "tattoo")
|
||||
end
|
||||
|
||||
function OpenSurgeonShop()
|
||||
local config = GetDefaultConfig()
|
||||
config.headBlend = true
|
||||
config.faceFeatures = true
|
||||
OpenShop(config, false, "surgeon")
|
||||
end
|
||||
|
||||
AddEventHandler("onResourceStop", function(resource)
|
||||
if resource == GetCurrentResourceName() then
|
||||
if Config.BossManagedOutfits then
|
||||
Management.RemoveItems()
|
||||
end
|
||||
end
|
||||
end)
|
41
resources/[il]/illenium-appearance/client/defaults.lua
Normal file
@ -0,0 +1,41 @@
|
||||
local function getComponentConfig()
|
||||
return {
|
||||
masks = not Config.DisableComponents.Masks,
|
||||
upperBody = not Config.DisableComponents.UpperBody,
|
||||
lowerBody = not Config.DisableComponents.LowerBody,
|
||||
bags = not Config.DisableComponents.Bags,
|
||||
shoes = not Config.DisableComponents.Shoes,
|
||||
scarfAndChains = not Config.DisableComponents.ScarfAndChains,
|
||||
bodyArmor = not Config.DisableComponents.BodyArmor,
|
||||
shirts = not Config.DisableComponents.Shirts,
|
||||
decals = not Config.DisableComponents.Decals,
|
||||
jackets = not Config.DisableComponents.Jackets
|
||||
}
|
||||
end
|
||||
|
||||
local function getPropConfig()
|
||||
return {
|
||||
hats = not Config.DisableProps.Hats,
|
||||
glasses = not Config.DisableProps.Glasses,
|
||||
ear = not Config.DisableProps.Ear,
|
||||
watches = not Config.DisableProps.Watches,
|
||||
bracelets = not Config.DisableProps.Bracelets
|
||||
}
|
||||
end
|
||||
|
||||
function GetDefaultConfig()
|
||||
return {
|
||||
ped = false,
|
||||
headBlend = false,
|
||||
faceFeatures = false,
|
||||
headOverlays = false,
|
||||
components = false,
|
||||
componentConfig = getComponentConfig(),
|
||||
props = false,
|
||||
propConfig = getPropConfig(),
|
||||
tattoos = false,
|
||||
enableExit = true,
|
||||
hasTracker = Config.PreventTrackerRemoval and Framework.HasTracker(),
|
||||
automaticFade = Config.AutomaticFade
|
||||
}
|
||||
end
|
@ -0,0 +1,57 @@
|
||||
if not Framework.ESX() then return end
|
||||
|
||||
local client = client
|
||||
local firstSpawn = false
|
||||
|
||||
AddEventHandler("esx_skin:resetFirstSpawn", function()
|
||||
firstSpawn = true
|
||||
end)
|
||||
|
||||
AddEventHandler("esx_skin:playerRegistered", function()
|
||||
if(firstSpawn) then
|
||||
InitializeCharacter(Framework.GetGender(true))
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent("skinchanger:loadSkin2", function(ped, skin)
|
||||
if not skin.model then skin.model = "mp_m_freemode_01" end
|
||||
client.setPedAppearance(ped, skin)
|
||||
Framework.CachePed()
|
||||
end)
|
||||
|
||||
RegisterNetEvent("skinchanger:getSkin", function(cb)
|
||||
while not Framework.PlayerData do
|
||||
Wait(1000)
|
||||
end
|
||||
lib.callback("illenium-appearance:server:getAppearance", false, function(appearance)
|
||||
cb(appearance)
|
||||
Framework.CachePed()
|
||||
end)
|
||||
end)
|
||||
|
||||
RegisterNetEvent("skinchanger:loadSkin", function(skin, cb)
|
||||
if skin.model then
|
||||
client.setPlayerAppearance(skin)
|
||||
else -- add validation invisible when failed registration (maybe server restarted when apply skin)
|
||||
SetInitialClothes(Config.InitialPlayerClothes[Framework.GetGender(true)])
|
||||
end
|
||||
if Framework.PlayerData and Framework.PlayerData.loadout then
|
||||
TriggerEvent("esx:restoreLoadout")
|
||||
end
|
||||
Framework.CachePed()
|
||||
if cb ~= nil then
|
||||
cb()
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent("skinchanger:loadClothes", function(_, clothes)
|
||||
local components = Framework.ConvertComponents(clothes, client.getPedComponents(cache.ped))
|
||||
local props = Framework.ConvertProps(clothes, client.getPedProps(cache.ped))
|
||||
|
||||
client.setPedComponents(cache.ped, components)
|
||||
client.setPedProps(cache.ped, props)
|
||||
end)
|
||||
|
||||
RegisterNetEvent("esx_skin:openSaveableMenu", function(onSubmit, onCancel)
|
||||
InitializeCharacter(Framework.GetGender(true), onSubmit, onCancel)
|
||||
end)
|
@ -0,0 +1,85 @@
|
||||
if not Framework.ESX() then return end
|
||||
|
||||
local ESX = exports["es_extended"]:getSharedObject()
|
||||
Framework.PlayerData = nil
|
||||
|
||||
RegisterNetEvent("esx:playerLoaded", function(xPlayer)
|
||||
Framework.PlayerData = xPlayer
|
||||
client.job = Framework.PlayerData.job
|
||||
client.gang = Framework.PlayerData.gang
|
||||
client.citizenid = Framework.PlayerData.identifier
|
||||
InitAppearance()
|
||||
end)
|
||||
|
||||
RegisterNetEvent("esx:onPlayerLogout", function()
|
||||
Framework.PlayerData = nil
|
||||
end)
|
||||
|
||||
RegisterNetEvent("esx:setJob", function(job)
|
||||
Framework.PlayerData.job = job
|
||||
client.job = Framework.PlayerData.job
|
||||
client.gang = Framework.PlayerData.job
|
||||
end)
|
||||
|
||||
local function getRankInputValues(rankList)
|
||||
local rankValues = {}
|
||||
for k, v in pairs(rankList) do
|
||||
rankValues[#rankValues + 1] = {
|
||||
label = v.label,
|
||||
value = v.grade
|
||||
}
|
||||
end
|
||||
return rankValues
|
||||
end
|
||||
|
||||
function Framework.GetPlayerGender()
|
||||
Framework.PlayerData = ESX.GetPlayerData()
|
||||
if Framework.PlayerData.sex == "f" then
|
||||
return "Female"
|
||||
end
|
||||
return "Male"
|
||||
end
|
||||
|
||||
function Framework.UpdatePlayerData()
|
||||
local data = ESX.GetPlayerData()
|
||||
if data.job then
|
||||
Framework.PlayerData = data
|
||||
client.job = Framework.PlayerData.job
|
||||
client.gang = Framework.PlayerData.job
|
||||
end
|
||||
client.citizenid = Framework.PlayerData.identifier
|
||||
end
|
||||
|
||||
function Framework.HasTracker()
|
||||
return false
|
||||
end
|
||||
|
||||
function Framework.CheckPlayerMeta()
|
||||
Framework.PlayerData = ESX.GetPlayerData()
|
||||
return Framework.PlayerData.dead or IsPedCuffed(Framework.PlayerData.ped)
|
||||
end
|
||||
|
||||
function Framework.IsPlayerAllowed(citizenid)
|
||||
return citizenid == Framework.PlayerData.identifier
|
||||
end
|
||||
|
||||
function Framework.GetRankInputValues(type)
|
||||
local jobGrades = lib.callback.await("illenium-appearance:server:esx:getGradesForJob", false, client[type].name)
|
||||
return getRankInputValues(jobGrades)
|
||||
end
|
||||
|
||||
function Framework.GetJobGrade()
|
||||
return client.job.grade
|
||||
end
|
||||
|
||||
function Framework.GetGangGrade()
|
||||
return client.gang.grade
|
||||
end
|
||||
|
||||
function Framework.CachePed()
|
||||
ESX.SetPlayerData("ped", cache.ped)
|
||||
end
|
||||
|
||||
function Framework.RestorePlayerArmour()
|
||||
return nil
|
||||
end
|
@ -0,0 +1,11 @@
|
||||
function Framework.GetGender(isNew)
|
||||
if isNew or not Config.GenderBasedOnPed then
|
||||
return Framework.GetPlayerGender()
|
||||
end
|
||||
|
||||
local model = client.getPedModel(cache.ped)
|
||||
if model == "mp_f_freemode_01" then
|
||||
return "Female"
|
||||
end
|
||||
return "Male"
|
||||
end
|
@ -0,0 +1,30 @@
|
||||
if not Framework.QBCore() then return end
|
||||
|
||||
local client = client
|
||||
|
||||
-- Backwards Compatible Events
|
||||
|
||||
RegisterNetEvent("qb-clothing:client:openMenu", function()
|
||||
local config = GetDefaultConfig()
|
||||
config.ped = true
|
||||
config.headBlend = true
|
||||
config.faceFeatures = true
|
||||
config.headOverlays = true
|
||||
config.components = true
|
||||
config.props = true
|
||||
config.tattoos = true
|
||||
OpenShop(config, true, "all")
|
||||
end)
|
||||
|
||||
RegisterNetEvent("qb-clothing:client:openOutfitMenu", function()
|
||||
OpenMenu(nil, "outfit")
|
||||
end)
|
||||
|
||||
RegisterNetEvent("qb-clothing:client:loadOutfit", LoadJobOutfit)
|
||||
|
||||
RegisterNetEvent("qb-multicharacter:client:chooseChar", function()
|
||||
client.setPedTattoos(cache.ped, {})
|
||||
ClearPedDecorations(cache.ped)
|
||||
|
||||
TriggerServerEvent("illenium-appearance:server:resetOutfitCache")
|
||||
end)
|
107
resources/[il]/illenium-appearance/client/framework/qb/main.lua
Normal file
@ -0,0 +1,107 @@
|
||||
if not Framework.QBCore() then return end
|
||||
|
||||
local client = client
|
||||
|
||||
local QBCore = exports["qb-core"]:GetCoreObject()
|
||||
|
||||
local PlayerData = QBCore.Functions.GetPlayerData()
|
||||
|
||||
local function getRankInputValues(rankList)
|
||||
local rankValues = {}
|
||||
for k, v in pairs(rankList) do
|
||||
rankValues[#rankValues + 1] = {
|
||||
label = v.name,
|
||||
value = k
|
||||
}
|
||||
end
|
||||
return rankValues
|
||||
end
|
||||
|
||||
local function setClientParams()
|
||||
client.job = PlayerData.job
|
||||
client.gang = PlayerData.gang
|
||||
client.citizenid = PlayerData.citizenid
|
||||
end
|
||||
|
||||
function Framework.GetPlayerGender()
|
||||
if PlayerData.charinfo.gender == 1 then
|
||||
return "Female"
|
||||
end
|
||||
return "Male"
|
||||
end
|
||||
|
||||
function Framework.UpdatePlayerData()
|
||||
PlayerData = QBCore.Functions.GetPlayerData()
|
||||
setClientParams()
|
||||
end
|
||||
|
||||
function Framework.HasTracker()
|
||||
return QBCore.Functions.GetPlayerData().metadata["tracker"]
|
||||
end
|
||||
|
||||
function Framework.CheckPlayerMeta()
|
||||
return PlayerData.metadata["isdead"] or PlayerData.metadata["inlaststand"] or PlayerData.metadata["ishandcuffed"]
|
||||
end
|
||||
|
||||
function Framework.IsPlayerAllowed(citizenid)
|
||||
return citizenid == PlayerData.citizenid
|
||||
end
|
||||
|
||||
function Framework.GetRankInputValues(type)
|
||||
local grades = QBCore.Shared.Jobs[client.job.name].grades
|
||||
if type == "gang" then
|
||||
grades = QBCore.Shared.Gangs[client.gang.name].grades
|
||||
end
|
||||
return getRankInputValues(grades)
|
||||
end
|
||||
|
||||
function Framework.GetJobGrade()
|
||||
return client.job.grade.level
|
||||
end
|
||||
|
||||
function Framework.GetGangGrade()
|
||||
return client.gang.grade.level
|
||||
end
|
||||
|
||||
RegisterNetEvent("QBCore:Client:OnJobUpdate", function(JobInfo)
|
||||
PlayerData.job = JobInfo
|
||||
client.job = JobInfo
|
||||
ResetBlips()
|
||||
end)
|
||||
|
||||
RegisterNetEvent("QBCore:Client:OnGangUpdate", function(GangInfo)
|
||||
PlayerData.gang = GangInfo
|
||||
client.gang = GangInfo
|
||||
ResetBlips()
|
||||
end)
|
||||
|
||||
RegisterNetEvent("QBCore:Client:SetDuty", function(duty)
|
||||
if PlayerData and PlayerData.job then
|
||||
PlayerData.job.onduty = duty
|
||||
client.job = PlayerData.job
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent("QBCore:Client:OnPlayerLoaded", function()
|
||||
InitAppearance()
|
||||
end)
|
||||
|
||||
RegisterNetEvent("qb-clothes:client:CreateFirstCharacter", function()
|
||||
QBCore.Functions.GetPlayerData(function(pd)
|
||||
PlayerData = pd
|
||||
setClientParams()
|
||||
InitializeCharacter(Framework.GetGender(true))
|
||||
end)
|
||||
end)
|
||||
|
||||
function Framework.CachePed()
|
||||
return nil
|
||||
end
|
||||
|
||||
function Framework.RestorePlayerArmour()
|
||||
Framework.UpdatePlayerData()
|
||||
if PlayerData and PlayerData.metadata then
|
||||
Wait(1000)
|
||||
SetPedArmour(cache.ped, PlayerData.metadata["armor"])
|
||||
end
|
||||
end
|
@ -0,0 +1,190 @@
|
||||
if not Framework.QBCore() then return end
|
||||
|
||||
local client = client
|
||||
|
||||
local skinData = {
|
||||
["face2"] = {
|
||||
item = 0,
|
||||
texture = 0,
|
||||
defaultItem = 0,
|
||||
defaultTexture = 0,
|
||||
},
|
||||
["facemix"] = {
|
||||
skinMix = 0,
|
||||
shapeMix = 0,
|
||||
defaultSkinMix = 0.0,
|
||||
defaultShapeMix = 0.0,
|
||||
},
|
||||
}
|
||||
|
||||
RegisterNetEvent("illenium-appearance:client:migration:load-qb-clothing-skin", function(playerSkin)
|
||||
local model = playerSkin.model
|
||||
model = model ~= nil and tonumber(model) or false
|
||||
Citizen.CreateThread(function()
|
||||
lib.requestModel(model, 1000)
|
||||
SetPlayerModel(cache.playerId, model)
|
||||
Wait(150)
|
||||
SetPedComponentVariation(cache.ped, 0, 0, 0, 2)
|
||||
TriggerEvent("illenium-appearance:client:migration:load-qb-clothing-clothes", playerSkin, cache.ped)
|
||||
SetModelAsNoLongerNeeded(model)
|
||||
end)
|
||||
end)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:client:migration:load-qb-clothing-clothes", function(playerSkin, ped)
|
||||
local data = json.decode(playerSkin.skin)
|
||||
if ped == nil then ped = cache.ped end
|
||||
|
||||
for i = 0, 11 do
|
||||
SetPedComponentVariation(ped, i, 0, 0, 0)
|
||||
end
|
||||
|
||||
for i = 0, 7 do
|
||||
ClearPedProp(ped, i)
|
||||
end
|
||||
|
||||
-- Face
|
||||
if not data["facemix"] or not data["face2"] then
|
||||
data["facemix"] = skinData["facemix"]
|
||||
data["facemix"].shapeMix = data["facemix"].defaultShapeMix
|
||||
data["facemix"].skinMix = data["facemix"].defaultSkinMix
|
||||
data["face2"] = skinData["face2"]
|
||||
end
|
||||
|
||||
SetPedHeadBlendData(ped, data["face"].item, data["face2"].item, nil, data["face"].texture, data["face2"].texture, nil, data["facemix"].shapeMix, data["facemix"].skinMix, nil, true)
|
||||
|
||||
-- Pants
|
||||
SetPedComponentVariation(ped, 4, data["pants"].item, 0, 0)
|
||||
SetPedComponentVariation(ped, 4, data["pants"].item, data["pants"].texture, 0)
|
||||
|
||||
-- Hair
|
||||
SetPedComponentVariation(ped, 2, data["hair"].item, 0, 0)
|
||||
SetPedHairColor(ped, data["hair"].texture, data["hair"].texture)
|
||||
|
||||
-- Eyebrows
|
||||
SetPedHeadOverlay(ped, 2, data["eyebrows"].item, 1.0)
|
||||
SetPedHeadOverlayColor(ped, 2, 1, data["eyebrows"].texture, 0)
|
||||
|
||||
-- Beard
|
||||
SetPedHeadOverlay(ped, 1, data["beard"].item, 1.0)
|
||||
SetPedHeadOverlayColor(ped, 1, 1, data["beard"].texture, 0)
|
||||
|
||||
-- Blush
|
||||
SetPedHeadOverlay(ped, 5, data["blush"].item, 1.0)
|
||||
SetPedHeadOverlayColor(ped, 5, 1, data["blush"].texture, 0)
|
||||
|
||||
-- Lipstick
|
||||
SetPedHeadOverlay(ped, 8, data["lipstick"].item, 1.0)
|
||||
SetPedHeadOverlayColor(ped, 8, 1, data["lipstick"].texture, 0)
|
||||
|
||||
-- Makeup
|
||||
SetPedHeadOverlay(ped, 4, data["makeup"].item, 1.0)
|
||||
SetPedHeadOverlayColor(ped, 4, 1, data["makeup"].texture, 0)
|
||||
|
||||
-- Ageing
|
||||
SetPedHeadOverlay(ped, 3, data["ageing"].item, 1.0)
|
||||
SetPedHeadOverlayColor(ped, 3, 1, data["ageing"].texture, 0)
|
||||
|
||||
-- Arms
|
||||
SetPedComponentVariation(ped, 3, data["arms"].item, 0, 2)
|
||||
SetPedComponentVariation(ped, 3, data["arms"].item, data["arms"].texture, 0)
|
||||
|
||||
-- T-Shirt
|
||||
SetPedComponentVariation(ped, 8, data["t-shirt"].item, 0, 2)
|
||||
SetPedComponentVariation(ped, 8, data["t-shirt"].item, data["t-shirt"].texture, 0)
|
||||
|
||||
-- Vest
|
||||
SetPedComponentVariation(ped, 9, data["vest"].item, 0, 2)
|
||||
SetPedComponentVariation(ped, 9, data["vest"].item, data["vest"].texture, 0)
|
||||
|
||||
-- Torso 2
|
||||
SetPedComponentVariation(ped, 11, data["torso2"].item, 0, 2)
|
||||
SetPedComponentVariation(ped, 11, data["torso2"].item, data["torso2"].texture, 0)
|
||||
|
||||
-- Shoes
|
||||
SetPedComponentVariation(ped, 6, data["shoes"].item, 0, 2)
|
||||
SetPedComponentVariation(ped, 6, data["shoes"].item, data["shoes"].texture, 0)
|
||||
|
||||
-- Mask
|
||||
SetPedComponentVariation(ped, 1, data["mask"].item, 0, 2)
|
||||
SetPedComponentVariation(ped, 1, data["mask"].item, data["mask"].texture, 0)
|
||||
|
||||
-- Badge
|
||||
SetPedComponentVariation(ped, 10, data["decals"].item, 0, 2)
|
||||
SetPedComponentVariation(ped, 10, data["decals"].item, data["decals"].texture, 0)
|
||||
|
||||
-- Accessory
|
||||
SetPedComponentVariation(ped, 7, data["accessory"].item, 0, 2)
|
||||
SetPedComponentVariation(ped, 7, data["accessory"].item, data["accessory"].texture, 0)
|
||||
|
||||
-- Bag
|
||||
SetPedComponentVariation(ped, 5, data["bag"].item, 0, 2)
|
||||
SetPedComponentVariation(ped, 5, data["bag"].item, data["bag"].texture, 0)
|
||||
|
||||
-- Hat
|
||||
if data["hat"].item ~= -1 and data["hat"].item ~= 0 then
|
||||
SetPedPropIndex(ped, 0, data["hat"].item, data["hat"].texture, true)
|
||||
else
|
||||
ClearPedProp(ped, 0)
|
||||
end
|
||||
|
||||
-- Glass
|
||||
if data["glass"].item ~= -1 and data["glass"].item ~= 0 then
|
||||
SetPedPropIndex(ped, 1, data["glass"].item, data["glass"].texture, true)
|
||||
else
|
||||
ClearPedProp(ped, 1)
|
||||
end
|
||||
|
||||
-- Ear
|
||||
if data["ear"].item ~= -1 and data["ear"].item ~= 0 then
|
||||
SetPedPropIndex(ped, 2, data["ear"].item, data["ear"].texture, true)
|
||||
else
|
||||
ClearPedProp(ped, 2)
|
||||
end
|
||||
|
||||
-- Watch
|
||||
if data["watch"].item ~= -1 and data["watch"].item ~= 0 then
|
||||
SetPedPropIndex(ped, 6, data["watch"].item, data["watch"].texture, true)
|
||||
else
|
||||
ClearPedProp(ped, 6)
|
||||
end
|
||||
|
||||
-- Bracelet
|
||||
if data["bracelet"].item ~= -1 and data["bracelet"].item ~= 0 then
|
||||
SetPedPropIndex(ped, 7, data["bracelet"].item, data["bracelet"].texture, true)
|
||||
else
|
||||
ClearPedProp(ped, 7)
|
||||
end
|
||||
|
||||
if data["eye_color"].item ~= -1 and data["eye_color"].item ~= 0 then
|
||||
SetPedEyeColor(ped, data["eye_color"].item)
|
||||
end
|
||||
|
||||
if data["moles"].item ~= -1 and data["moles"].item ~= 0 then
|
||||
SetPedHeadOverlay(ped, 9, data["moles"].item, (data["moles"].texture / 10))
|
||||
end
|
||||
|
||||
SetPedFaceFeature(ped, 0, (data["nose_0"].item / 10))
|
||||
SetPedFaceFeature(ped, 1, (data["nose_1"].item / 10))
|
||||
SetPedFaceFeature(ped, 2, (data["nose_2"].item / 10))
|
||||
SetPedFaceFeature(ped, 3, (data["nose_3"].item / 10))
|
||||
SetPedFaceFeature(ped, 4, (data["nose_4"].item / 10))
|
||||
SetPedFaceFeature(ped, 5, (data["nose_5"].item / 10))
|
||||
SetPedFaceFeature(ped, 6, (data["eyebrown_high"].item / 10))
|
||||
SetPedFaceFeature(ped, 7, (data["eyebrown_forward"].item / 10))
|
||||
SetPedFaceFeature(ped, 8, (data["cheek_1"].item / 10))
|
||||
SetPedFaceFeature(ped, 9, (data["cheek_2"].item / 10))
|
||||
SetPedFaceFeature(ped, 10,(data["cheek_3"].item / 10))
|
||||
SetPedFaceFeature(ped, 11, (data["eye_opening"].item / 10))
|
||||
SetPedFaceFeature(ped, 12, (data["lips_thickness"].item / 10))
|
||||
SetPedFaceFeature(ped, 13, (data["jaw_bone_width"].item / 10))
|
||||
SetPedFaceFeature(ped, 14, (data["jaw_bone_back_lenght"].item / 10))
|
||||
SetPedFaceFeature(ped, 15, (data["chimp_bone_lowering"].item / 10))
|
||||
SetPedFaceFeature(ped, 16, (data["chimp_bone_lenght"].item / 10))
|
||||
SetPedFaceFeature(ped, 17, (data["chimp_bone_width"].item / 10))
|
||||
SetPedFaceFeature(ped, 18, (data["chimp_hole"].item / 10))
|
||||
SetPedFaceFeature(ped, 19, (data["neck_thikness"].item / 10))
|
||||
|
||||
local appearance = client.getPedAppearance(ped)
|
||||
|
||||
TriggerServerEvent("illenium-appearance:server:migrate-qb-clothing-skin", playerSkin.citizenid, appearance)
|
||||
end)
|
@ -0,0 +1,27 @@
|
||||
if not Config.BossManagedOutfits then return end
|
||||
|
||||
if Framework.ESX() then return end
|
||||
|
||||
function Management.RemoveItems()
|
||||
if GetResourceState(Management.ResourceName) ~= "started" then return end
|
||||
|
||||
if Management.ItemIDs.Boss then
|
||||
exports[Management.ResourceName]:RemoveBossMenuItem(Management.ItemIDs.Boss)
|
||||
end
|
||||
if Management.ItemIDs.Gang then
|
||||
exports[Management.ResourceName]:RemoveGangMenuItem(Management.ItemIDs.Gang)
|
||||
end
|
||||
end
|
||||
|
||||
function Management.AddBackMenuItem(managementMenu, args)
|
||||
local bossMenuEvent = "qb-bossmenu:client:OpenMenu"
|
||||
if args.type == "Gang" then
|
||||
bossMenuEvent = "qb-gangmenu:client:OpenMenu"
|
||||
end
|
||||
|
||||
managementMenu.options[#managementMenu.options+1] = {
|
||||
title = _L("menu.returnTitle"),
|
||||
icon = "fa-solid fa-angle-left",
|
||||
event = bossMenuEvent
|
||||
}
|
||||
end
|
15
resources/[il]/illenium-appearance/client/management/esx.lua
Normal file
@ -0,0 +1,15 @@
|
||||
if not Config.BossManagedOutfits then return end
|
||||
|
||||
if not Framework.ESX() then return end
|
||||
|
||||
function Management.RemoveItems()
|
||||
-- Do nothing
|
||||
end
|
||||
|
||||
function Management.AddItems()
|
||||
-- Do nothing
|
||||
end
|
||||
|
||||
function Management.AddBackMenuItem()
|
||||
-- Do nothing
|
||||
end
|
@ -0,0 +1,26 @@
|
||||
if not Config.BossManagedOutfits then return end
|
||||
|
||||
Management = {}
|
||||
|
||||
Management.ItemIDs = {
|
||||
Gang = nil,
|
||||
Boss = nil
|
||||
}
|
||||
|
||||
function Management.IsQB()
|
||||
local resName = "qb-management"
|
||||
if GetResourceState(resName) ~= "missing" then
|
||||
Management.ResourceName = resName
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function Management.IsQBX()
|
||||
local resName = "qbx_management"
|
||||
if GetResourceState(resName) ~= "missing" then
|
||||
Management.ResourceName = resName
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
21
resources/[il]/illenium-appearance/client/management/qb.lua
Normal file
@ -0,0 +1,21 @@
|
||||
if not Config.BossManagedOutfits then return end
|
||||
|
||||
if not Management.IsQB() then return end
|
||||
|
||||
function Management.AddItems()
|
||||
local menuItem = {
|
||||
header = _L("outfitManagement.title"),
|
||||
icon = "fa-solid fa-shirt",
|
||||
params = {
|
||||
event = "illenium-appearance:client:OutfitManagementMenu",
|
||||
args = {}
|
||||
}
|
||||
}
|
||||
menuItem.txt = _L("outfitManagement.jobText")
|
||||
menuItem.params.args.type = "Job"
|
||||
Management.ItemIDs.Boss = exports[Management.ResourceName]:AddBossMenuItem(menuItem)
|
||||
|
||||
menuItem.txt = _L("outfitManagement.gangText")
|
||||
menuItem.params.args.type = "Gang"
|
||||
Management.ItemIDs.Gang = exports[Management.ResourceName]:AddGangMenuItem(menuItem)
|
||||
end
|
19
resources/[il]/illenium-appearance/client/management/qbx.lua
Normal file
@ -0,0 +1,19 @@
|
||||
if not Config.BossManagedOutfits then return end
|
||||
|
||||
if not Management.IsQBX() then return end
|
||||
|
||||
function Management.AddItems()
|
||||
local menuItem = {
|
||||
title = _L("outfitManagement.title"),
|
||||
icon = "fa-solid fa-shirt",
|
||||
event = "illenium-appearance:client:OutfitManagementMenu",
|
||||
args = {}
|
||||
}
|
||||
menuItem.description = _L("outfitManagement.jobText")
|
||||
menuItem.args.type = "Job"
|
||||
Management.ItemIDs.Boss = exports[Management.ResourceName]:AddBossMenuItem(menuItem)
|
||||
|
||||
menuItem.description = _L("outfitManagement.gangText")
|
||||
menuItem.args.type = "Gang"
|
||||
Management.ItemIDs.Gang = exports[Management.ResourceName]:AddGangMenuItem(menuItem)
|
||||
end
|
142
resources/[il]/illenium-appearance/client/outfits.lua
Normal file
@ -0,0 +1,142 @@
|
||||
local function typeof(var)
|
||||
local _type = type(var);
|
||||
if (_type ~= "table" and _type ~= "userdata") then
|
||||
return _type;
|
||||
end
|
||||
local _meta = getmetatable(var);
|
||||
if (_meta ~= nil and _meta._NAME ~= nil) then
|
||||
return _meta._NAME;
|
||||
else
|
||||
return _type;
|
||||
end
|
||||
end
|
||||
|
||||
function LoadJobOutfit(oData)
|
||||
local ped = cache.ped
|
||||
|
||||
local data = oData.outfitData
|
||||
|
||||
if typeof(data) ~= "table" then
|
||||
data = json.decode(data)
|
||||
end
|
||||
|
||||
-- Pants
|
||||
if data["pants"] ~= nil then
|
||||
SetPedComponentVariation(ped, 4, data["pants"].item, data["pants"].texture, 0)
|
||||
end
|
||||
|
||||
-- Arms
|
||||
if data["arms"] ~= nil then
|
||||
SetPedComponentVariation(ped, 3, data["arms"].item, data["arms"].texture, 0)
|
||||
end
|
||||
|
||||
-- T-Shirt
|
||||
if data["t-shirt"] ~= nil then
|
||||
SetPedComponentVariation(ped, 8, data["t-shirt"].item, data["t-shirt"].texture, 0)
|
||||
end
|
||||
|
||||
-- Vest
|
||||
if data["vest"] ~= nil then
|
||||
SetPedComponentVariation(ped, 9, data["vest"].item, data["vest"].texture, 0)
|
||||
end
|
||||
|
||||
-- Torso 2
|
||||
if data["torso2"] ~= nil then
|
||||
SetPedComponentVariation(ped, 11, data["torso2"].item, data["torso2"].texture, 0)
|
||||
end
|
||||
|
||||
-- Shoes
|
||||
if data["shoes"] ~= nil then
|
||||
SetPedComponentVariation(ped, 6, data["shoes"].item, data["shoes"].texture, 0)
|
||||
end
|
||||
|
||||
-- Badge
|
||||
if data["decals"] ~= nil then
|
||||
SetPedComponentVariation(ped, 10, data["decals"].item, data["decals"].texture, 0)
|
||||
end
|
||||
|
||||
-- Accessory
|
||||
local tracker = Config.TrackerClothingOptions
|
||||
|
||||
if data["accessory"] ~= nil then
|
||||
if Framework.HasTracker() then
|
||||
SetPedComponentVariation(ped, 7, tracker.drawable, tracker.texture, 0)
|
||||
else
|
||||
SetPedComponentVariation(ped, 7, data["accessory"].item, data["accessory"].texture, 0)
|
||||
end
|
||||
else
|
||||
if Framework.HasTracker() then
|
||||
SetPedComponentVariation(ped, 7, tracker.drawable, tracker.texture, 0)
|
||||
else
|
||||
local drawableId = GetPedDrawableVariation(ped, 7)
|
||||
|
||||
if drawableId ~= -1 then
|
||||
local textureId = GetPedTextureVariation(ped, 7)
|
||||
if drawableId == tracker.drawable and textureId == tracker.texture then
|
||||
SetPedComponentVariation(ped, 7, -1, 0, 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Mask
|
||||
if data["mask"] ~= nil then
|
||||
SetPedComponentVariation(ped, 1, data["mask"].item, data["mask"].texture, 0)
|
||||
end
|
||||
|
||||
-- Bag
|
||||
if data["bag"] ~= nil then
|
||||
SetPedComponentVariation(ped, 5, data["bag"].item, data["bag"].texture, 0)
|
||||
end
|
||||
|
||||
-- Hat
|
||||
if data["hat"] ~= nil then
|
||||
if data["hat"].item ~= -1 and data["hat"].item ~= 0 then
|
||||
SetPedPropIndex(ped, 0, data["hat"].item, data["hat"].texture, true)
|
||||
else
|
||||
ClearPedProp(ped, 0)
|
||||
end
|
||||
end
|
||||
|
||||
-- Glass
|
||||
if data["glass"] ~= nil then
|
||||
if data["glass"].item ~= -1 and data["glass"].item ~= 0 then
|
||||
SetPedPropIndex(ped, 1, data["glass"].item, data["glass"].texture, true)
|
||||
else
|
||||
ClearPedProp(ped, 1)
|
||||
end
|
||||
end
|
||||
|
||||
-- Ear
|
||||
if data["ear"] ~= nil then
|
||||
if data["ear"].item ~= -1 and data["ear"].item ~= 0 then
|
||||
SetPedPropIndex(ped, 2, data["ear"].item, data["ear"].texture, true)
|
||||
else
|
||||
ClearPedProp(ped, 2)
|
||||
end
|
||||
end
|
||||
|
||||
local length = 0
|
||||
for _ in pairs(data) do
|
||||
length = length + 1
|
||||
end
|
||||
|
||||
if Config.PersistUniforms and length > 1 then
|
||||
TriggerServerEvent("illenium-appearance:server:syncUniform", {
|
||||
jobName = oData.jobName,
|
||||
gender = oData.gender,
|
||||
label = oData.name
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
RegisterNetEvent("illenium-appearance:client:loadJobOutfit", LoadJobOutfit)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:client:openOutfitMenu", function()
|
||||
OpenMenu(nil, "outfit")
|
||||
end)
|
||||
|
||||
RegisterNetEvent("illenium-apearance:client:outfitsCommand", function(isJob)
|
||||
local outfits = GetPlayerJobOutfits(isJob)
|
||||
TriggerEvent("illenium-appearance:client:openJobOutfitsMenu", outfits)
|
||||
end)
|
5
resources/[il]/illenium-appearance/client/props.lua
Normal file
@ -0,0 +1,5 @@
|
||||
lib.onCache('ped', function(value)
|
||||
if Config.AlwaysKeepProps then
|
||||
SetPedCanLosePropsOnDamage(value, false, 0)
|
||||
end
|
||||
end)
|
17
resources/[il]/illenium-appearance/client/radial/ox.lua
Normal file
@ -0,0 +1,17 @@
|
||||
if not Radial.IsOX() then return end
|
||||
|
||||
function Radial.Add(title, event)
|
||||
lib.addRadialItem({
|
||||
id = Radial.MenuID,
|
||||
icon = "shirt",
|
||||
label = title,
|
||||
event = event,
|
||||
onSelect = function()
|
||||
TriggerEvent(event)
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
function Radial.Remove()
|
||||
lib.removeRadialItem(Radial.MenuID)
|
||||
end
|
16
resources/[il]/illenium-appearance/client/radial/qb.lua
Normal file
@ -0,0 +1,16 @@
|
||||
if not Radial.IsQBX() and not Radial.IsQB() then return end
|
||||
|
||||
function Radial.Add(title, event)
|
||||
exports[Radial.ResourceName]:AddOption({
|
||||
id = Radial.MenuID,
|
||||
title = title,
|
||||
icon = "shirt",
|
||||
type = "client",
|
||||
event = event,
|
||||
shouldClose = true
|
||||
}, Radial.MenuID)
|
||||
end
|
||||
|
||||
function Radial.Remove()
|
||||
exports[Radial.ResourceName]:RemoveOption(Radial.MenuID)
|
||||
end
|
71
resources/[il]/illenium-appearance/client/radial/radial.lua
Normal file
@ -0,0 +1,71 @@
|
||||
Radial = {}
|
||||
|
||||
Radial.MenuID = "open_clothing_menu"
|
||||
|
||||
local radialOptionAdded = false
|
||||
|
||||
function Radial.IsOX()
|
||||
local resName = "ox_lib"
|
||||
if GetResourceState(resName) ~= "missing" and Config.UseOxRadial then
|
||||
Radial.ResourceName = resName
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function Radial.IsQB()
|
||||
local resName = "qb-radialmenu"
|
||||
if GetResourceState(resName) ~= "missing" then
|
||||
Radial.ResourceName = resName
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function Radial.IsQBX()
|
||||
local resName = "qbx_radialmenu"
|
||||
if GetResourceState(resName) ~= "missing" then
|
||||
Radial.ResourceName = resName
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function Radial.AddOption(currentZone)
|
||||
if not Config.UseRadialMenu then return end
|
||||
|
||||
if not currentZone then
|
||||
Radial.Remove()
|
||||
return
|
||||
end
|
||||
local event, title
|
||||
local zoneEvents = {
|
||||
clothingRoom = {"illenium-appearance:client:OpenClothingRoom", _L("menu.title")},
|
||||
playerOutfitRoom = {"illenium-appearance:client:OpenPlayerOutfitRoom", _L("menu.outfitsTitle")},
|
||||
clothing = {"illenium-appearance:client:openClothingShopMenu", _L("menu.clothingShopTitle")},
|
||||
barber = {"illenium-appearance:client:OpenBarberShop", _L("menu.barberShopTitle")},
|
||||
tattoo = {"illenium-appearance:client:OpenTattooShop", _L("menu.tattooShopTitle")},
|
||||
surgeon = {"illenium-appearance:client:OpenSurgeonShop", _L("menu.surgeonShopTitle")},
|
||||
}
|
||||
if zoneEvents[currentZone.name] then
|
||||
event, title = table.unpack(zoneEvents[currentZone.name])
|
||||
end
|
||||
|
||||
Radial.Add(title, event)
|
||||
radialOptionAdded = true
|
||||
end
|
||||
|
||||
function Radial.RemoveOption()
|
||||
if radialOptionAdded then
|
||||
Radial.Remove()
|
||||
radialOptionAdded = false
|
||||
end
|
||||
end
|
||||
|
||||
AddEventHandler("onResourceStop", function(resource)
|
||||
if resource == GetCurrentResourceName() then
|
||||
if Config.UseOxRadial and GetResourceState("ox_lib") == "started" or GetResourceState("qb-radialmenu") == "started" then
|
||||
Radial.RemoveOption()
|
||||
end
|
||||
end
|
||||
end)
|
28
resources/[il]/illenium-appearance/client/stats.lua
Normal file
@ -0,0 +1,28 @@
|
||||
local stats = nil
|
||||
|
||||
local function ResetRechargeMultipliers()
|
||||
SetPlayerHealthRechargeMultiplier(cache.playerId, 0.0)
|
||||
SetPlayerHealthRechargeLimit(cache.playerId, 0.0)
|
||||
end
|
||||
|
||||
function BackupPlayerStats()
|
||||
stats = {
|
||||
health = GetEntityHealth(cache.ped),
|
||||
armour = GetPedArmour(cache.ped)
|
||||
}
|
||||
end
|
||||
|
||||
function RestorePlayerStats()
|
||||
if stats then
|
||||
SetEntityMaxHealth(cache.ped, 200)
|
||||
Wait(1000) -- Safety Delay
|
||||
SetEntityHealth(cache.ped, stats.health)
|
||||
SetPedArmour(cache.ped, stats.armour)
|
||||
ResetRechargeMultipliers()
|
||||
stats = nil
|
||||
return
|
||||
end
|
||||
|
||||
-- If no stats are backed up, restore from the framework
|
||||
Framework.RestorePlayerArmour()
|
||||
end
|
55
resources/[il]/illenium-appearance/client/target/ox.lua
Normal file
@ -0,0 +1,55 @@
|
||||
if not Config.UseTarget then return end
|
||||
|
||||
if not Target.IsOX() then return end
|
||||
|
||||
local ZoneIDMap = {}
|
||||
|
||||
local function convert(options)
|
||||
local distance = options.distance
|
||||
options = options.options
|
||||
for _, v in pairs(options) do
|
||||
v.onSelect = v.action
|
||||
v.distance = v.distance or distance
|
||||
v.name = v.name or v.label
|
||||
v.groups = v.job or v.gang
|
||||
v.type = nil
|
||||
v.action = nil
|
||||
|
||||
v.job = nil
|
||||
v.gang = nil
|
||||
v.qtarget = true
|
||||
end
|
||||
|
||||
return options
|
||||
end
|
||||
|
||||
function Target.RemoveZone(zone)
|
||||
exports["ox_target"]:removeZone(ZoneIDMap[zone])
|
||||
end
|
||||
|
||||
function Target.AddTargetEntity(entity, parameters)
|
||||
exports["ox_target"]:addLocalEntity(entity, convert(parameters))
|
||||
end
|
||||
|
||||
function Target.AddBoxZone(name, coords, size, parameters)
|
||||
local rotation = parameters.rotation
|
||||
ZoneIDMap[name] = exports["ox_target"]:addBoxZone({
|
||||
coords = coords,
|
||||
size = size,
|
||||
rotation = rotation,
|
||||
debug = Config.Debug,
|
||||
options = convert(parameters)
|
||||
})
|
||||
end
|
||||
|
||||
function Target.AddPolyZone(name, points, parameters)
|
||||
ZoneIDMap[name] = exports["ox_target"]:addPolyZone({
|
||||
points = points,
|
||||
debug = Config.Debug,
|
||||
options = convert(parameters)
|
||||
})
|
||||
end
|
||||
|
||||
function Target.IsTargetStarted()
|
||||
return GetResourceState("ox_target") == "started"
|
||||
end
|
34
resources/[il]/illenium-appearance/client/target/qb.lua
Normal file
@ -0,0 +1,34 @@
|
||||
if not Config.UseTarget then return end
|
||||
|
||||
if not Target.IsQB() then return end
|
||||
|
||||
function Target.RemoveZone(zone)
|
||||
exports["qb-target"]:RemoveZone(zone)
|
||||
end
|
||||
|
||||
function Target.AddTargetEntity(entity, parameters)
|
||||
exports["qb-target"]:AddTargetEntity(entity, parameters)
|
||||
end
|
||||
|
||||
function Target.AddBoxZone(name, coords, size, parameters)
|
||||
exports["qb-target"]:AddBoxZone(name, coords, size.x, size.y, {
|
||||
name = name,
|
||||
debugPoly = Config.Debug,
|
||||
minZ = coords.z - 2,
|
||||
maxZ = coords.z + 2,
|
||||
heading = coords.w
|
||||
}, parameters)
|
||||
end
|
||||
|
||||
function Target.AddPolyZone(name, points, parameters)
|
||||
exports["qb-target"]:AddPolyZone(name, points, {
|
||||
name = name,
|
||||
debugPoly = Config.Debug,
|
||||
minZ = points[1].z - 2,
|
||||
maxZ = points[1].z + 2
|
||||
}, parameters)
|
||||
end
|
||||
|
||||
function Target.IsTargetStarted()
|
||||
return GetResourceState("qb-target") == "started"
|
||||
end
|
192
resources/[il]/illenium-appearance/client/target/target.lua
Normal file
@ -0,0 +1,192 @@
|
||||
if not Config.UseTarget then return end
|
||||
|
||||
local TargetPeds = {
|
||||
Store = {},
|
||||
ClothingRoom = {},
|
||||
PlayerOutfitRoom = {}
|
||||
}
|
||||
|
||||
Target = {}
|
||||
|
||||
function Target.IsOX()
|
||||
return GetResourceState("ox_target") ~= "missing"
|
||||
end
|
||||
|
||||
function Target.IsQB()
|
||||
return GetResourceState("qb-target") ~= "missing"
|
||||
end
|
||||
|
||||
local function RemoveTargetPeds(peds)
|
||||
for i = 1, #peds, 1 do
|
||||
DeletePed(peds[i])
|
||||
end
|
||||
end
|
||||
|
||||
local function RemoveTargets()
|
||||
if Config.EnablePedsForShops then
|
||||
RemoveTargetPeds(TargetPeds.Store)
|
||||
else
|
||||
for k, v in pairs(Config.Stores) do
|
||||
Target.RemoveZone(v.type .. k)
|
||||
end
|
||||
end
|
||||
|
||||
if Config.EnablePedsForClothingRooms then
|
||||
RemoveTargetPeds(TargetPeds.ClothingRoom)
|
||||
else
|
||||
for k, v in pairs(Config.ClothingRooms) do
|
||||
Target.RemoveZone("clothing_" .. (v.job or v.gang) .. k)
|
||||
end
|
||||
end
|
||||
|
||||
if Config.EnablePedsForPlayerOutfitRooms then
|
||||
RemoveTargetPeds(TargetPeds.PlayerOutfitRoom)
|
||||
else
|
||||
for k in pairs(Config.PlayerOutfitRooms) do
|
||||
Target.RemoveZone("playeroutfitroom_" .. k)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
AddEventHandler("onResourceStop", function(resource)
|
||||
if resource == GetCurrentResourceName() then
|
||||
if Target.IsTargetStarted() then
|
||||
RemoveTargets()
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local function CreatePedAtCoords(pedModel, coords, scenario)
|
||||
pedModel = type(pedModel) == "string" and joaat(pedModel) or pedModel
|
||||
lib.requestModel(pedModel)
|
||||
local ped = CreatePed(0, pedModel, coords.x, coords.y, coords.z - 0.98, coords.w, false, false)
|
||||
TaskStartScenarioInPlace(ped, scenario, true)
|
||||
FreezeEntityPosition(ped, true)
|
||||
SetEntityVisible(ped, true)
|
||||
SetEntityInvincible(ped, true)
|
||||
PlaceObjectOnGroundProperly(ped)
|
||||
SetBlockingOfNonTemporaryEvents(ped, true)
|
||||
return ped
|
||||
end
|
||||
|
||||
local function SetupStoreTarget(targetConfig, action, k, v)
|
||||
local parameters = {
|
||||
options = {{
|
||||
type = "client",
|
||||
action = action,
|
||||
icon = targetConfig.icon,
|
||||
label = targetConfig.label
|
||||
}},
|
||||
distance = targetConfig.distance,
|
||||
rotation = v.rotation
|
||||
}
|
||||
|
||||
if Config.EnablePedsForShops then
|
||||
TargetPeds.Store[k] = CreatePedAtCoords(v.targetModel or targetConfig.model, v.coords, v.targetScenario or targetConfig.scenario)
|
||||
Target.AddTargetEntity(TargetPeds.Store[k], parameters)
|
||||
elseif v.usePoly then
|
||||
Target.AddPolyZone(v.type .. k, v.points, parameters)
|
||||
else
|
||||
Target.AddBoxZone(v.type .. k, v.coords, v.size, parameters)
|
||||
end
|
||||
end
|
||||
|
||||
local function SetupStoreTargets()
|
||||
for k, v in pairs(Config.Stores) do
|
||||
local targetConfig = Config.TargetConfig[v.type]
|
||||
local action
|
||||
|
||||
if v.type == "barber" then
|
||||
action = OpenBarberShop
|
||||
elseif v.type == "clothing" then
|
||||
action = function()
|
||||
TriggerEvent("illenium-appearance:client:openClothingShopMenu")
|
||||
end
|
||||
elseif v.type == "tattoo" then
|
||||
action = OpenTattooShop
|
||||
elseif v.type == "surgeon" then
|
||||
action = OpenSurgeonShop
|
||||
end
|
||||
|
||||
if not (Config.RCoreTattoosCompatibility and v.type == "tattoo") then
|
||||
SetupStoreTarget(targetConfig, action, k, v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function SetupClothingRoomTargets()
|
||||
for k, v in pairs(Config.ClothingRooms) do
|
||||
local targetConfig = Config.TargetConfig["clothingroom"]
|
||||
local action = function()
|
||||
local outfits = GetPlayerJobOutfits(v.job)
|
||||
TriggerEvent("illenium-appearance:client:openJobOutfitsMenu", outfits)
|
||||
end
|
||||
|
||||
local parameters = {
|
||||
options = {{
|
||||
type = "client",
|
||||
action = action,
|
||||
icon = targetConfig.icon,
|
||||
label = targetConfig.label,
|
||||
canInteract = v.job and CheckDuty or nil,
|
||||
job = v.job,
|
||||
gang = v.gang
|
||||
}},
|
||||
distance = targetConfig.distance,
|
||||
rotation = v.rotation
|
||||
}
|
||||
|
||||
local key = "clothing_" .. (v.job or v.gang) .. k
|
||||
if Config.EnablePedsForClothingRooms then
|
||||
TargetPeds.ClothingRoom[k] = CreatePedAtCoords(v.targetModel or targetConfig.model, v.coords, v.targetScenario or targetConfig.scenario)
|
||||
Target.AddTargetEntity(TargetPeds.ClothingRoom[k], parameters)
|
||||
elseif v.usePoly then
|
||||
Target.AddPolyZone(key, v.points, parameters)
|
||||
else
|
||||
Target.AddBoxZone(key, v.coords, v.size, parameters)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function SetupPlayerOutfitRoomTargets()
|
||||
for k, v in pairs(Config.PlayerOutfitRooms) do
|
||||
local targetConfig = Config.TargetConfig["playeroutfitroom"]
|
||||
|
||||
local parameters = {
|
||||
options = {{
|
||||
type = "client",
|
||||
action = function()
|
||||
OpenOutfitRoom(v)
|
||||
end,
|
||||
icon = targetConfig.icon,
|
||||
label = targetConfig.label,
|
||||
canInteract = function()
|
||||
return IsPlayerAllowedForOutfitRoom(v)
|
||||
end
|
||||
}},
|
||||
distance = targetConfig.distance,
|
||||
rotation = v.rotation
|
||||
}
|
||||
|
||||
if Config.EnablePedsForPlayerOutfitRooms then
|
||||
TargetPeds.PlayerOutfitRoom[k] = CreatePedAtCoords(v.targetModel or targetConfig.model, v.coords, v.targetScenario or targetConfig.scenario)
|
||||
Target.AddTargetEntity(TargetPeds.PlayerOutfitRoom[k], parameters)
|
||||
elseif v.usePoly then
|
||||
Target.AddPolyZone("playeroutfitroom_" .. k, v.points, parameters)
|
||||
else
|
||||
Target.AddBoxZone("playeroutfitroom_" .. k, v.coords, v.size, parameters)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function SetupTargets()
|
||||
SetupStoreTargets()
|
||||
SetupClothingRoomTargets()
|
||||
SetupPlayerOutfitRoomTargets()
|
||||
end
|
||||
|
||||
CreateThread(function()
|
||||
if Config.UseTarget then
|
||||
SetupTargets()
|
||||
end
|
||||
end)
|
197
resources/[il]/illenium-appearance/client/zones.lua
Normal file
@ -0,0 +1,197 @@
|
||||
if Config.UseTarget then return end
|
||||
|
||||
local currentZone = nil
|
||||
|
||||
local Zones = {
|
||||
Store = {},
|
||||
ClothingRoom = {},
|
||||
PlayerOutfitRoom = {}
|
||||
}
|
||||
|
||||
local function RemoveZones()
|
||||
for i = 1, #Zones.Store do
|
||||
if Zones.Store[i]["remove"] then
|
||||
Zones.Store[i]:remove()
|
||||
end
|
||||
end
|
||||
for i = 1, #Zones.ClothingRoom do
|
||||
Zones.ClothingRoom[i]:remove()
|
||||
end
|
||||
for i = 1, #Zones.PlayerOutfitRoom do
|
||||
Zones.PlayerOutfitRoom[i]:remove()
|
||||
end
|
||||
end
|
||||
|
||||
local function lookupZoneIndexFromID(zones, id)
|
||||
for i = 1, #zones do
|
||||
if zones[i].id == id then
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function onStoreEnter(data)
|
||||
local index = lookupZoneIndexFromID(Zones.Store, data.id)
|
||||
local store = Config.Stores[index]
|
||||
|
||||
local jobName = (store.job and client.job.name) or (store.gang and client.gang.name)
|
||||
if jobName == (store.job or store.gang) then
|
||||
currentZone = {
|
||||
name = store.type,
|
||||
index = index
|
||||
}
|
||||
local prefix = Config.UseRadialMenu and "" or "[E] "
|
||||
if currentZone.name == "clothing" then
|
||||
lib.showTextUI(prefix .. string.format(_L("textUI.clothing"), Config.ClothingCost), Config.TextUIOptions)
|
||||
elseif currentZone.name == "barber" then
|
||||
lib.showTextUI(prefix .. string.format(_L("textUI.barber"), Config.BarberCost), Config.TextUIOptions)
|
||||
elseif currentZone.name == "tattoo" then
|
||||
lib.showTextUI(prefix .. string.format(_L("textUI.tattoo"), Config.TattooCost), Config.TextUIOptions)
|
||||
elseif currentZone.name == "surgeon" then
|
||||
lib.showTextUI(prefix .. string.format(_L("textUI.surgeon"), Config.SurgeonCost), Config.TextUIOptions)
|
||||
end
|
||||
Radial.AddOption(currentZone)
|
||||
end
|
||||
end
|
||||
|
||||
local function onClothingRoomEnter(data)
|
||||
local index = lookupZoneIndexFromID(Zones.ClothingRoom, data.id)
|
||||
local clothingRoom = Config.ClothingRooms[index]
|
||||
|
||||
local jobName = clothingRoom.job and client.job.name or client.gang.name
|
||||
if jobName == (clothingRoom.job or clothingRoom.gang) then
|
||||
if CheckDuty() or clothingRoom.gang then
|
||||
currentZone = {
|
||||
name = "clothingRoom",
|
||||
index = index
|
||||
}
|
||||
local prefix = Config.UseRadialMenu and "" or "[E] "
|
||||
lib.showTextUI(prefix .. _L("textUI.clothingRoom"), Config.TextUIOptions)
|
||||
Radial.AddOption(currentZone)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function onPlayerOutfitRoomEnter(data)
|
||||
local index = lookupZoneIndexFromID(Zones.PlayerOutfitRoom, data.id)
|
||||
local playerOutfitRoom = Config.PlayerOutfitRooms[index]
|
||||
|
||||
local isAllowed = IsPlayerAllowedForOutfitRoom(playerOutfitRoom)
|
||||
if isAllowed then
|
||||
currentZone = {
|
||||
name = "playerOutfitRoom",
|
||||
index = index
|
||||
}
|
||||
local prefix = Config.UseRadialMenu and "" or "[E] "
|
||||
lib.showTextUI(prefix .. _L("textUI.playerOutfitRoom"), Config.TextUIOptions)
|
||||
Radial.AddOption(currentZone)
|
||||
end
|
||||
end
|
||||
|
||||
local function onZoneExit()
|
||||
currentZone = nil
|
||||
Radial.RemoveOption()
|
||||
lib.hideTextUI()
|
||||
end
|
||||
|
||||
local function SetupZone(store, onEnter, onExit)
|
||||
if Config.RCoreTattoosCompatibility and store.type == "tattoo" then
|
||||
return {}
|
||||
end
|
||||
|
||||
if Config.UseRadialMenu or store.usePoly then
|
||||
return lib.zones.poly({
|
||||
points = store.points,
|
||||
debug = Config.Debug,
|
||||
onEnter = onEnter,
|
||||
onExit = onExit
|
||||
})
|
||||
end
|
||||
|
||||
return lib.zones.box({
|
||||
coords = store.coords,
|
||||
size = store.size,
|
||||
rotation = store.rotation,
|
||||
debug = Config.Debug,
|
||||
onEnter = onEnter,
|
||||
onExit = onExit
|
||||
})
|
||||
end
|
||||
|
||||
local function SetupStoreZones()
|
||||
for _, v in pairs(Config.Stores) do
|
||||
Zones.Store[#Zones.Store + 1] = SetupZone(v, onStoreEnter, onZoneExit)
|
||||
end
|
||||
end
|
||||
|
||||
local function SetupClothingRoomZones()
|
||||
for _, v in pairs(Config.ClothingRooms) do
|
||||
Zones.ClothingRoom[#Zones.ClothingRoom + 1] = SetupZone(v, onClothingRoomEnter, onZoneExit)
|
||||
end
|
||||
end
|
||||
|
||||
local function SetupPlayerOutfitRoomZones()
|
||||
for _, v in pairs(Config.PlayerOutfitRooms) do
|
||||
Zones.PlayerOutfitRoom[#Zones.PlayerOutfitRoom + 1] = SetupZone(v, onPlayerOutfitRoomEnter, onZoneExit)
|
||||
end
|
||||
end
|
||||
|
||||
local function SetupZones()
|
||||
SetupStoreZones()
|
||||
SetupClothingRoomZones()
|
||||
SetupPlayerOutfitRoomZones()
|
||||
end
|
||||
|
||||
local function ZonesLoop()
|
||||
Wait(1000)
|
||||
while true do
|
||||
local sleep = 1000
|
||||
if currentZone then
|
||||
sleep = 5
|
||||
if IsControlJustReleased(0, 38) then
|
||||
if currentZone.name == "clothingRoom" then
|
||||
local clothingRoom = Config.ClothingRooms[currentZone.index]
|
||||
local outfits = GetPlayerJobOutfits(clothingRoom.job)
|
||||
TriggerEvent("illenium-appearance:client:openJobOutfitsMenu", outfits)
|
||||
elseif currentZone.name == "playerOutfitRoom" then
|
||||
local outfitRoom = Config.PlayerOutfitRooms[currentZone.index]
|
||||
OpenOutfitRoom(outfitRoom)
|
||||
elseif currentZone.name == "clothing" then
|
||||
TriggerEvent("illenium-appearance:client:openClothingShopMenu")
|
||||
elseif currentZone.name == "barber" then
|
||||
OpenBarberShop()
|
||||
elseif currentZone.name == "tattoo" then
|
||||
OpenTattooShop()
|
||||
elseif currentZone.name == "surgeon" then
|
||||
OpenSurgeonShop()
|
||||
end
|
||||
end
|
||||
end
|
||||
Wait(sleep)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
CreateThread(function()
|
||||
SetupZones()
|
||||
if not Config.UseRadialMenu then
|
||||
ZonesLoop()
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler("onResourceStop", function(resource)
|
||||
if resource == GetCurrentResourceName() then
|
||||
RemoveZones()
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:client:OpenClothingRoom", function()
|
||||
local clothingRoom = Config.ClothingRooms[currentZone.index]
|
||||
local outfits = GetPlayerJobOutfits(clothingRoom.job)
|
||||
TriggerEvent("illenium-appearance:client:openJobOutfitsMenu", outfits)
|
||||
end)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:client:OpenPlayerOutfitRoom", function()
|
||||
local outfitRoom = Config.PlayerOutfitRooms[currentZone.index]
|
||||
OpenOutfitRoom(outfitRoom)
|
||||
end)
|
82
resources/[il]/illenium-appearance/fxmanifest.lua
Normal file
@ -0,0 +1,82 @@
|
||||
fx_version 'cerulean'
|
||||
game "gta5"
|
||||
|
||||
author "snakewiz & iLLeniumStudios"
|
||||
description "A flexible player customization script for FiveM servers."
|
||||
repository "https://github.com/iLLeniumStudios/illenium-appearance"
|
||||
version "v5.6.1"
|
||||
|
||||
lua54 "yes"
|
||||
|
||||
client_scripts {
|
||||
"game/constants.lua",
|
||||
"game/util.lua",
|
||||
"game/customization.lua",
|
||||
"game/nui.lua",
|
||||
"client/outfits.lua",
|
||||
"client/common.lua",
|
||||
"client/zones.lua",
|
||||
"client/framework/framework.lua",
|
||||
"client/framework/qb/compatibility.lua",
|
||||
"client/framework/qb/main.lua",
|
||||
"client/framework/qb/migrate.lua",
|
||||
"client/framework/esx/compatibility.lua",
|
||||
"client/framework/esx/main.lua",
|
||||
"client/target/target.lua",
|
||||
"client/target/qb.lua",
|
||||
"client/target/ox.lua",
|
||||
"client/management/management.lua",
|
||||
"client/management/common.lua",
|
||||
"client/management/qb.lua",
|
||||
"client/management/qbx.lua",
|
||||
"client/management/esx.lua",
|
||||
"client/radial/radial.lua",
|
||||
"client/radial/qb.lua",
|
||||
"client/radial/ox.lua",
|
||||
"client/stats.lua",
|
||||
"client/defaults.lua",
|
||||
"client/blips.lua",
|
||||
"client/props.lua",
|
||||
"client/client.lua",
|
||||
}
|
||||
|
||||
server_scripts {
|
||||
"@oxmysql/lib/MySQL.lua",
|
||||
"server/database/database.lua",
|
||||
"server/database/jobgrades.lua",
|
||||
"server/database/managementoutfits.lua",
|
||||
"server/database/playeroutfitcodes.lua",
|
||||
"server/database/playeroutfits.lua",
|
||||
"server/database/players.lua",
|
||||
"server/database/playerskins.lua",
|
||||
"server/database/users.lua",
|
||||
"server/framework/qb/main.lua",
|
||||
"server/framework/qb/migrate.lua",
|
||||
"server/framework/esx/main.lua",
|
||||
"server/framework/esx/migrate.lua",
|
||||
"server/framework/esx/callbacks.lua",
|
||||
"server/framework/esx/management.lua",
|
||||
"server/util.lua",
|
||||
"server/server.lua",
|
||||
"server/permissions.lua"
|
||||
}
|
||||
|
||||
shared_scripts {
|
||||
"shared/config.lua",
|
||||
"shared/blacklist.lua",
|
||||
"shared/peds.lua",
|
||||
"shared/tattoos.lua",
|
||||
"shared/theme.lua",
|
||||
"shared/framework/framework.lua",
|
||||
"shared/framework/esx/util.lua",
|
||||
"locales/locales.lua",
|
||||
"locales/da.lua",
|
||||
"@ox_lib/init.lua"
|
||||
}
|
||||
|
||||
files {
|
||||
"web/dist/index.html",
|
||||
"web/dist/assets/*.js"
|
||||
}
|
||||
|
||||
ui_page "web/dist/index.html"
|
366
resources/[il]/illenium-appearance/game/constants.lua
Normal file
@ -0,0 +1,366 @@
|
||||
constants = {}
|
||||
constants.PED_COMPONENTS_IDS = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
|
||||
constants.PED_PROPS_IDS = {0, 1, 2, 6, 7}
|
||||
|
||||
constants.FACE_FEATURES = {
|
||||
"noseWidth",
|
||||
"nosePeakHigh",
|
||||
"nosePeakSize",
|
||||
"noseBoneHigh",
|
||||
"nosePeakLowering",
|
||||
"noseBoneTwist",
|
||||
"eyeBrownHigh",
|
||||
"eyeBrownForward",
|
||||
"cheeksBoneHigh",
|
||||
"cheeksBoneWidth",
|
||||
"cheeksWidth",
|
||||
"eyesOpening",
|
||||
"lipsThickness",
|
||||
"jawBoneWidth",
|
||||
"jawBoneBackSize",
|
||||
"chinBoneLowering",
|
||||
"chinBoneLenght",
|
||||
"chinBoneSize",
|
||||
"chinHole",
|
||||
"neckThickness",
|
||||
}
|
||||
|
||||
constants.HEAD_OVERLAYS = {
|
||||
"blemishes",
|
||||
"beard",
|
||||
"eyebrows",
|
||||
"ageing",
|
||||
"makeUp",
|
||||
"blush",
|
||||
"complexion",
|
||||
"sunDamage",
|
||||
"lipstick",
|
||||
"moleAndFreckles",
|
||||
"chestHair",
|
||||
"bodyBlemishes",
|
||||
}
|
||||
|
||||
-- Thanks to rootcause for the eye colors names and hair decorations hashes.
|
||||
constants.EYE_COLORS = {
|
||||
"Grøn",
|
||||
"Emerald",
|
||||
"Lyseblå",
|
||||
"Mørkeblå",
|
||||
"Lysebrun",
|
||||
"Mørkebrun",
|
||||
"Hazel",
|
||||
"Mørkegrå",
|
||||
"Lysegrå",
|
||||
"Pink",
|
||||
"Gul",
|
||||
"Lilla",
|
||||
"Sort",
|
||||
"Hint af grå",
|
||||
"Tequila Sunrise",
|
||||
"Atomic",
|
||||
"Warp",
|
||||
"ECola",
|
||||
"Space Ranger",
|
||||
"Ying Yang",
|
||||
"Bullseye",
|
||||
"Lizard",
|
||||
"Dragon",
|
||||
"Extra Terrestrial",
|
||||
"Goat",
|
||||
"Smiley",
|
||||
"Possessed",
|
||||
"Demon",
|
||||
"Infected",
|
||||
"Alien",
|
||||
"Undead",
|
||||
"Zombie",
|
||||
}
|
||||
|
||||
constants.HAIR_DECORATIONS = {
|
||||
male = {
|
||||
[0] = { `mpbeach_overlays`, `FM_Hair_Fuzz` },
|
||||
[1] = { `multiplayer_overlays`, `NG_M_Hair_001` },
|
||||
[2] = { `multiplayer_overlays`, `NG_M_Hair_002` },
|
||||
[3] = { `multiplayer_overlays`, `NG_M_Hair_003` },
|
||||
[4] = { `multiplayer_overlays`, `NG_M_Hair_004` },
|
||||
[5] = { `multiplayer_overlays`, `NG_M_Hair_005` },
|
||||
[6] = { `multiplayer_overlays`, `NG_M_Hair_006` },
|
||||
[7] = { `multiplayer_overlays`, `NG_M_Hair_007` },
|
||||
[8] = { `multiplayer_overlays`, `NG_M_Hair_008` },
|
||||
[9] = { `multiplayer_overlays`, `NG_M_Hair_009` },
|
||||
[10] = { `multiplayer_overlays`, `NG_M_Hair_013` },
|
||||
[11] = { `multiplayer_overlays`, `NG_M_Hair_002` },
|
||||
[12] = { `multiplayer_overlays`, `NG_M_Hair_011` },
|
||||
[13] = { `multiplayer_overlays`, `NG_M_Hair_012` },
|
||||
[14] = { `multiplayer_overlays`, `NG_M_Hair_014` },
|
||||
[15] = { `multiplayer_overlays`, `NG_M_Hair_015` },
|
||||
[16] = { `multiplayer_overlays`, `NGBea_M_Hair_000` },
|
||||
[17] = { `multiplayer_overlays`, `NGBea_M_Hair_001` },
|
||||
[18] = { `multiplayer_overlays`, `NGBus_M_Hair_000` },
|
||||
[19] = { `multiplayer_overlays`, `NGBus_M_Hair_001` },
|
||||
[20] = { `multiplayer_overlays`, `NGHip_M_Hair_000` },
|
||||
[21] = { `multiplayer_overlays`, `NGHip_M_Hair_001` },
|
||||
[22] = { `multiplayer_overlays`, `NGInd_M_Hair_000` },
|
||||
[24] = { `mplowrider_overlays`, `LR_M_Hair_000` },
|
||||
[25] = { `mplowrider_overlays`, `LR_M_Hair_001` },
|
||||
[26] = { `mplowrider_overlays`, `LR_M_Hair_002` },
|
||||
[27] = { `mplowrider_overlays`, `LR_M_Hair_003` },
|
||||
[28] = { `mplowrider2_overlays`, `LR_M_Hair_004` },
|
||||
[29] = { `mplowrider2_overlays`, `LR_M_Hair_005` },
|
||||
[30] = { `mplowrider2_overlays`, `LR_M_Hair_006` },
|
||||
[31] = { `mpbiker_overlays`, `MP_Biker_Hair_000_M` },
|
||||
[32] = { `mpbiker_overlays`, `MP_Biker_Hair_001_M` },
|
||||
[33] = { `mpbiker_overlays`, `MP_Biker_Hair_002_M` },
|
||||
[34] = { `mpbiker_overlays`, `MP_Biker_Hair_003_M` },
|
||||
[35] = { `mpbiker_overlays`, `MP_Biker_Hair_004_M` },
|
||||
[36] = { `mpbiker_overlays`, `MP_Biker_Hair_005_M` },
|
||||
[37] = { `multiplayer_overlays`, `NG_M_Hair_001` },
|
||||
[38] = { `multiplayer_overlays`, `NG_M_Hair_002` },
|
||||
[39] = { `multiplayer_overlays`, `NG_M_Hair_003` },
|
||||
[40] = { `multiplayer_overlays`, `NG_M_Hair_004` },
|
||||
[41] = { `multiplayer_overlays`, `NG_M_Hair_005` },
|
||||
[42] = { `multiplayer_overlays`, `NG_M_Hair_006` },
|
||||
[43] = { `multiplayer_overlays`, `NG_M_Hair_007` },
|
||||
[44] = { `multiplayer_overlays`, `NG_M_Hair_008` },
|
||||
[45] = { `multiplayer_overlays`, `NG_M_Hair_009` },
|
||||
[46] = { `multiplayer_overlays`, `NG_M_Hair_013` },
|
||||
[47] = { `multiplayer_overlays`, `NG_M_Hair_002` },
|
||||
[48] = { `multiplayer_overlays`, `NG_M_Hair_011` },
|
||||
[49] = { `multiplayer_overlays`, `NG_M_Hair_012` },
|
||||
[50] = { `multiplayer_overlays`, `NG_M_Hair_014` },
|
||||
[51] = { `multiplayer_overlays`, `NG_M_Hair_015` },
|
||||
[52] = { `multiplayer_overlays`, `NGBea_M_Hair_000` },
|
||||
[53] = { `multiplayer_overlays`, `NGBea_M_Hair_001` },
|
||||
[54] = { `multiplayer_overlays`, `NGBus_M_Hair_000` },
|
||||
[55] = { `multiplayer_overlays`, `NGBus_M_Hair_001` },
|
||||
[56] = { `multiplayer_overlays`, `NGHip_M_Hair_000` },
|
||||
[57] = { `multiplayer_overlays`, `NGHip_M_Hair_001` },
|
||||
[58] = { `multiplayer_overlays`, `NGInd_M_Hair_000` },
|
||||
[59] = { `mplowrider_overlays`, `LR_M_Hair_000` },
|
||||
[60] = { `mplowrider_overlays`, `LR_M_Hair_001` },
|
||||
[61] = { `mplowrider_overlays`, `LR_M_Hair_002` },
|
||||
[62] = { `mplowrider_overlays`, `LR_M_Hair_003` },
|
||||
[63] = { `mplowrider2_overlays`, `LR_M_Hair_004` },
|
||||
[64] = { `mplowrider2_overlays`, `LR_M_Hair_005` },
|
||||
[65] = { `mplowrider2_overlays`, `LR_M_Hair_006` },
|
||||
[66] = { `mpbiker_overlays`, `MP_Biker_Hair_000_M` },
|
||||
[67] = { `mpbiker_overlays`, `MP_Biker_Hair_001_M` },
|
||||
[68] = { `mpbiker_overlays`, `MP_Biker_Hair_002_M` },
|
||||
[69] = { `mpbiker_overlays`, `MP_Biker_Hair_003_M` },
|
||||
[70] = { `mpbiker_overlays`, `MP_Biker_Hair_004_M` },
|
||||
[71] = { `mpbiker_overlays`, `MP_Biker_Hair_005_M` },
|
||||
[72] = { `mpgunrunning_overlays`, `MP_Gunrunning_Hair_M_000_M` },
|
||||
[73] = { `mpgunrunning_overlays`, `MP_Gunrunning_Hair_M_001_M` },
|
||||
[74] = { `mpVinewood_overlays`, `MP_Vinewood_Hair_M_000_M` },
|
||||
[75] = { `mptuner_overlays`, `MP_Tuner_Hair_001_M` },
|
||||
[76] = { `mpsecurity_overlays`, `MP_Security_Hair_001_M` },
|
||||
},
|
||||
|
||||
female = {
|
||||
[0] = { `mpbeach_overlays`, `FM_Hair_Fuzz` },
|
||||
[1] = { `multiplayer_overlays`, `NG_F_Hair_001` },
|
||||
[2] = { `multiplayer_overlays`, `NG_F_Hair_002` },
|
||||
[3] = { `multiplayer_overlays`, `NG_F_Hair_003` },
|
||||
[4] = { `multiplayer_overlays`, `NG_F_Hair_004` },
|
||||
[5] = { `multiplayer_overlays`, `NG_F_Hair_005` },
|
||||
[6] = { `multiplayer_overlays`, `NG_F_Hair_006` },
|
||||
[7] = { `multiplayer_overlays`, `NG_F_Hair_007` },
|
||||
[8] = { `multiplayer_overlays`, `NG_F_Hair_008` },
|
||||
[9] = { `multiplayer_overlays`, `NG_F_Hair_009` },
|
||||
[10] = { `multiplayer_overlays`, `NG_F_Hair_010` },
|
||||
[11] = { `multiplayer_overlays`, `NG_F_Hair_011` },
|
||||
[12] = { `multiplayer_overlays`, `NG_F_Hair_012` },
|
||||
[13] = { `multiplayer_overlays`, `NG_F_Hair_013` },
|
||||
[14] = { `multiplayer_overlays`, `NG_M_Hair_014` },
|
||||
[15] = { `multiplayer_overlays`, `NG_M_Hair_015` },
|
||||
[16] = { `multiplayer_overlays`, `NGBea_F_Hair_000` },
|
||||
[17] = { `multiplayer_overlays`, `NGBea_F_Hair_001` },
|
||||
[18] = { `multiplayer_overlays`, `NG_F_Hair_007` },
|
||||
[19] = { `multiplayer_overlays`, `NGBus_F_Hair_000` },
|
||||
[20] = { `multiplayer_overlays`, `NGBus_F_Hair_001` },
|
||||
[21] = { `multiplayer_overlays`, `NGBea_F_Hair_001` },
|
||||
[22] = { `multiplayer_overlays`, `NGHip_F_Hair_000` },
|
||||
[23] = { `multiplayer_overlays`, `NGInd_F_Hair_000` },
|
||||
[25] = { `mplowrider_overlays`, `LR_F_Hair_000` },
|
||||
[26] = { `mplowrider_overlays`, `LR_F_Hair_001` },
|
||||
[27] = { `mplowrider_overlays`, `LR_F_Hair_002` },
|
||||
[28] = { `mplowrider2_overlays`, `LR_F_Hair_003` },
|
||||
[29] = { `mplowrider2_overlays`, `LR_F_Hair_003` },
|
||||
[30] = { `mplowrider2_overlays`, `LR_F_Hair_004` },
|
||||
[31] = { `mplowrider2_overlays`, `LR_F_Hair_006` },
|
||||
[32] = { `mpbiker_overlays`, `MP_Biker_Hair_000_F` },
|
||||
[33] = { `mpbiker_overlays`, `MP_Biker_Hair_001_F` },
|
||||
[34] = { `mpbiker_overlays`, `MP_Biker_Hair_002_F` },
|
||||
[35] = { `mpbiker_overlays`, `MP_Biker_Hair_003_F` },
|
||||
[36] = { `multiplayer_overlays`, `NG_F_Hair_003` },
|
||||
[37] = { `mpbiker_overlays`, `MP_Biker_Hair_006_F` },
|
||||
[38] = { `mpbiker_overlays`, `MP_Biker_Hair_004_F` },
|
||||
[39] = { `multiplayer_overlays`, `NG_F_Hair_001` },
|
||||
[40] = { `multiplayer_overlays`, `NG_F_Hair_002` },
|
||||
[41] = { `multiplayer_overlays`, `NG_F_Hair_003` },
|
||||
[42] = { `multiplayer_overlays`, `NG_F_Hair_004` },
|
||||
[43] = { `multiplayer_overlays`, `NG_F_Hair_005` },
|
||||
[44] = { `multiplayer_overlays`, `NG_F_Hair_006` },
|
||||
[45] = { `multiplayer_overlays`, `NG_F_Hair_007` },
|
||||
[46] = { `multiplayer_overlays`, `NG_F_Hair_008` },
|
||||
[47] = { `multiplayer_overlays`, `NG_F_Hair_009` },
|
||||
[48] = { `multiplayer_overlays`, `NG_F_Hair_010` },
|
||||
[49] = { `multiplayer_overlays`, `NG_F_Hair_011` },
|
||||
[50] = { `multiplayer_overlays`, `NG_F_Hair_012` },
|
||||
[51] = { `multiplayer_overlays`, `NG_F_Hair_013` },
|
||||
[52] = { `multiplayer_overlays`, `NG_M_Hair_014` },
|
||||
[53] = { `multiplayer_overlays`, `NG_M_Hair_015` },
|
||||
[54] = { `multiplayer_overlays`, `NGBea_F_Hair_000` },
|
||||
[55] = { `multiplayer_overlays`, `NGBea_F_Hair_001` },
|
||||
[56] = { `multiplayer_overlays`, `NG_F_Hair_007` },
|
||||
[57] = { `multiplayer_overlays`, `NGBus_F_Hair_000` },
|
||||
[58] = { `multiplayer_overlays`, `NGBus_F_Hair_001` },
|
||||
[59] = { `multiplayer_overlays`, `NGBea_F_Hair_001` },
|
||||
[60] = { `multiplayer_overlays`, `NGHip_F_Hair_000` },
|
||||
[61] = { `multiplayer_overlays`, `NGInd_F_Hair_000` },
|
||||
[62] = { `mplowrider_overlays`, `LR_F_Hair_000` },
|
||||
[63] = { `mplowrider_overlays`, `LR_F_Hair_001` },
|
||||
[64] = { `mplowrider_overlays`, `LR_F_Hair_002` },
|
||||
[65] = { `mplowrider2_overlays`, `LR_F_Hair_003` },
|
||||
[66] = { `mplowrider2_overlays`, `LR_F_Hair_003` },
|
||||
[67] = { `mplowrider2_overlays`, `LR_F_Hair_004` },
|
||||
[68] = { `mplowrider2_overlays`, `LR_F_Hair_006` },
|
||||
[69] = { `mpbiker_overlays`, `MP_Biker_Hair_000_F` },
|
||||
[70] = { `mpbiker_overlays`, `MP_Biker_Hair_001_F` },
|
||||
[71] = { `mpbiker_overlays`, `MP_Biker_Hair_002_F` },
|
||||
[72] = { `mpbiker_overlays`, `MP_Biker_Hair_003_F` },
|
||||
[73] = { `multiplayer_overlays`, `NG_F_Hair_003` },
|
||||
[74] = { `mpbiker_overlays`, `MP_Biker_Hair_006_F` },
|
||||
[75] = { `mpbiker_overlays`, `MP_Biker_Hair_004_F` },
|
||||
[76] = { `mpgunrunning_overlays`, `MP_Gunrunning_Hair_F_000_F` },
|
||||
[77] = { `mpgunrunning_overlays`, `MP_Gunrunning_Hair_F_001_F` },
|
||||
[78] = { `mpVinewood_overlays`, `MP_Vinewood_Hair_F_000_F` },
|
||||
[79] = { `mptuner_overlays`, `MP_Tuner_Hair_000_F` },
|
||||
[80] = { `mpsecurity_overlays`, `MP_Security_Hair_000_F` },
|
||||
},
|
||||
}
|
||||
|
||||
constants.DATA_CLOTHES = {
|
||||
head = {
|
||||
animations = {
|
||||
on = {
|
||||
dict = "mp_masks@standard_car@ds@",
|
||||
anim = "put_on_mask",
|
||||
move = 51,
|
||||
duration = 600
|
||||
},
|
||||
off = {
|
||||
dict = "missheist_agency2ahelmet",
|
||||
anim = "take_off_helmet_stand",
|
||||
move = 51,
|
||||
duration = 1200
|
||||
}
|
||||
},
|
||||
components = {
|
||||
male = {
|
||||
{1, 0}
|
||||
},
|
||||
female = {
|
||||
{1, 0}
|
||||
}
|
||||
},
|
||||
props = {
|
||||
male = {
|
||||
{0, -1}
|
||||
},
|
||||
female = {}
|
||||
}
|
||||
},
|
||||
body = {
|
||||
animations = {
|
||||
on = {
|
||||
dict = "clothingtie",
|
||||
anim = "try_tie_negative_a",
|
||||
move = 51,
|
||||
duration = 1200
|
||||
},
|
||||
off = {
|
||||
dict = "clothingtie",
|
||||
anim = "try_tie_negative_a",
|
||||
move = 51,
|
||||
duration = 1200
|
||||
}
|
||||
},
|
||||
components = {
|
||||
male = {
|
||||
{11, 252},
|
||||
{3, 15},
|
||||
{8, 15},
|
||||
{10, 0},
|
||||
{5, 0}
|
||||
},
|
||||
female = {
|
||||
{11, 15},
|
||||
{8, 14},
|
||||
{3, 15},
|
||||
{10, 0},
|
||||
{5, 0}
|
||||
}
|
||||
},
|
||||
props = {
|
||||
male = {},
|
||||
female = {}
|
||||
}
|
||||
},
|
||||
bottom = {
|
||||
animations = {
|
||||
on = {
|
||||
dict = "re@construction",
|
||||
anim = "out_of_breath",
|
||||
move = 51,
|
||||
duration = 1300
|
||||
},
|
||||
off = {
|
||||
dict = "re@construction",
|
||||
anim = "out_of_breath",
|
||||
move = 51,
|
||||
duration = 1300
|
||||
}
|
||||
},
|
||||
components = {
|
||||
male = {
|
||||
{4, 61},
|
||||
{6, 34}
|
||||
},
|
||||
female = {
|
||||
{4, 15},
|
||||
{6, 35}
|
||||
}
|
||||
},
|
||||
props = {
|
||||
male = {},
|
||||
female = {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constants.CAMERAS = {
|
||||
default = {
|
||||
vec3(0, 2.2, 0.2),
|
||||
vec3(0, 0, -0.05),
|
||||
},
|
||||
head = {
|
||||
vec3(0, 0.9, 0.65),
|
||||
vec3(0, 0, 0.6),
|
||||
},
|
||||
body = {
|
||||
vec3(0, 1.2, 0.2),
|
||||
vec3(0, 0, 0.2),
|
||||
},
|
||||
bottom = {
|
||||
vec3(0, 0.98, -0.7),
|
||||
vec3(0, 0, -0.9),
|
||||
},
|
||||
}
|
||||
|
||||
constants.OFFSETS = {
|
||||
default = vec2(1.5, -1),
|
||||
head = vec2(0.7, -0.45),
|
||||
body = vec2(1.2, -0.45),
|
||||
bottom = vec2(0.7, -0.45),
|
||||
}
|
611
resources/[il]/illenium-appearance/game/customization.lua
Normal file
@ -0,0 +1,611 @@
|
||||
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)
|
||||
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)
|
136
resources/[il]/illenium-appearance/game/nui.lua
Normal file
@ -0,0 +1,136 @@
|
||||
local client = client
|
||||
|
||||
RegisterNUICallback("appearance_get_locales", function(_, cb)
|
||||
cb(Locales[GetConvar("illenium-appearance:locale", "en")].UI)
|
||||
end)
|
||||
|
||||
RegisterNUICallback("appearance_get_settings", function(_, cb)
|
||||
cb({ appearanceSettings = client.getAppearanceSettings() })
|
||||
end)
|
||||
|
||||
RegisterNUICallback("appearance_get_data", function(_, cb)
|
||||
Wait(250)
|
||||
local appearanceData = client.getAppearance()
|
||||
if appearanceData.tattoos then
|
||||
client.setPedTattoos(cache.ped, appearanceData.tattoos)
|
||||
end
|
||||
cb({ config = client.getConfig(), appearanceData = appearanceData })
|
||||
end)
|
||||
|
||||
RegisterNUICallback("appearance_set_camera", function(camera, cb)
|
||||
cb(1)
|
||||
client.setCamera(camera)
|
||||
end)
|
||||
|
||||
RegisterNUICallback("appearance_turn_around", function(_, cb)
|
||||
cb(1)
|
||||
client.pedTurn(cache.ped, 180.0)
|
||||
end)
|
||||
|
||||
RegisterNUICallback("appearance_rotate_camera", function(direction, cb)
|
||||
cb(1)
|
||||
client.rotateCamera(direction)
|
||||
end)
|
||||
|
||||
RegisterNUICallback("appearance_change_model", function(model, cb)
|
||||
local playerPed = client.setPlayerModel(model)
|
||||
|
||||
SetEntityHeading(cache.ped, client.getHeading())
|
||||
SetEntityInvincible(playerPed, true)
|
||||
TaskStandStill(playerPed, -1)
|
||||
|
||||
cb({
|
||||
appearanceSettings = client.getAppearanceSettings(),
|
||||
appearanceData = client.getPedAppearance(playerPed)
|
||||
})
|
||||
end)
|
||||
|
||||
RegisterNUICallback("appearance_change_component", function(component, cb)
|
||||
client.setPedComponent(cache.ped, component)
|
||||
cb(client.getComponentSettings(cache.ped, component.component_id))
|
||||
end)
|
||||
|
||||
RegisterNUICallback("appearance_change_prop", function(prop, cb)
|
||||
client.setPedProp(cache.ped, prop)
|
||||
cb(client.getPropSettings(cache.ped, prop.prop_id))
|
||||
end)
|
||||
|
||||
RegisterNUICallback("appearance_change_head_blend", function(headBlend, cb)
|
||||
cb(1)
|
||||
client.setPedHeadBlend(cache.ped, headBlend)
|
||||
end)
|
||||
|
||||
RegisterNUICallback("appearance_change_face_feature", function(faceFeatures, cb)
|
||||
cb(1)
|
||||
client.setPedFaceFeatures(cache.ped, faceFeatures)
|
||||
end)
|
||||
|
||||
RegisterNUICallback("appearance_change_head_overlay", function(headOverlays, cb)
|
||||
cb(1)
|
||||
client.setPedHeadOverlays(cache.ped, headOverlays)
|
||||
end)
|
||||
|
||||
RegisterNUICallback("appearance_change_hair", function(hair, cb)
|
||||
client.setPedHair(cache.ped, hair)
|
||||
cb(client.getHairSettings(cache.ped))
|
||||
end)
|
||||
|
||||
RegisterNUICallback("appearance_change_eye_color", function(eyeColor, cb)
|
||||
cb(1)
|
||||
client.setPedEyeColor(cache.ped, eyeColor)
|
||||
end)
|
||||
|
||||
RegisterNUICallback("appearance_apply_tattoo", function(data, cb)
|
||||
local paid = not data.tattoo or not Config.ChargePerTattoo or lib.callback.await("illenium-appearance:server:payForTattoo", false, data.tattoo)
|
||||
if paid then
|
||||
client.addPedTattoo(cache.ped, data.updatedTattoos or data)
|
||||
end
|
||||
cb(paid)
|
||||
end)
|
||||
|
||||
RegisterNUICallback("appearance_preview_tattoo", function(previewTattoo, cb)
|
||||
cb(1)
|
||||
client.setPreviewTattoo(cache.ped, previewTattoo.data, previewTattoo.tattoo)
|
||||
end)
|
||||
|
||||
RegisterNUICallback("appearance_delete_tattoo", function(data, cb)
|
||||
cb(1)
|
||||
client.removePedTattoo(cache.ped, data)
|
||||
end)
|
||||
|
||||
RegisterNUICallback("appearance_wear_clothes", function(dataWearClothes, cb)
|
||||
cb(1)
|
||||
client.wearClothes(dataWearClothes.data, dataWearClothes.key)
|
||||
end)
|
||||
|
||||
RegisterNUICallback("appearance_remove_clothes", function(clothes, cb)
|
||||
cb(1)
|
||||
client.removeClothes(clothes)
|
||||
end)
|
||||
|
||||
RegisterNUICallback("appearance_save", function(appearance, cb)
|
||||
cb(1)
|
||||
client.wearClothes(appearance, "head")
|
||||
client.wearClothes(appearance, "body")
|
||||
client.wearClothes(appearance, "bottom")
|
||||
client.exitPlayerCustomization(appearance)
|
||||
end)
|
||||
|
||||
RegisterNUICallback("appearance_exit", function(_, cb)
|
||||
cb(1)
|
||||
client.exitPlayerCustomization()
|
||||
end)
|
||||
|
||||
RegisterNUICallback("rotate_left", function(_, cb)
|
||||
cb(1)
|
||||
client.pedTurn(cache.ped, 10.0)
|
||||
end)
|
||||
|
||||
RegisterNUICallback("rotate_right", function(_, cb)
|
||||
cb(1)
|
||||
client.pedTurn(cache.ped, -10.0)
|
||||
end)
|
||||
|
||||
RegisterNUICallback("get_theme_configuration", function(_, cb)
|
||||
cb(Config.Theme)
|
||||
end)
|
439
resources/[il]/illenium-appearance/game/util.lua
Normal file
@ -0,0 +1,439 @@
|
||||
local hashesComputed = false
|
||||
local PED_TATTOOS = {}
|
||||
local pedModelsByHash = {}
|
||||
|
||||
local function tofloat(num)
|
||||
return num + 0.0
|
||||
end
|
||||
|
||||
local function isPedFreemodeModel(ped)
|
||||
local model = GetEntityModel(ped)
|
||||
return model == `mp_m_freemode_01` or model == `mp_f_freemode_01`
|
||||
end
|
||||
|
||||
local function computePedModelsByHash()
|
||||
for i = 1, #Config.Peds.pedConfig do
|
||||
local peds = Config.Peds.pedConfig[i].peds
|
||||
for j = 1, #peds do
|
||||
pedModelsByHash[joaat(peds[j])] = peds[j]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param ped number entity id
|
||||
---@return string
|
||||
--- Get the model name from an entity's model hash
|
||||
local function getPedModel(ped)
|
||||
if not hashesComputed then
|
||||
computePedModelsByHash()
|
||||
hashesComputed = true
|
||||
end
|
||||
return pedModelsByHash[GetEntityModel(ped)]
|
||||
end
|
||||
|
||||
---@param ped number entity id
|
||||
---@return table<number, table<string, number>>
|
||||
local function getPedComponents(ped)
|
||||
local size = #constants.PED_COMPONENTS_IDS
|
||||
local components = table.create(size, 0)
|
||||
|
||||
for i = 1, size do
|
||||
local componentId = constants.PED_COMPONENTS_IDS[i]
|
||||
components[i] = {
|
||||
component_id = componentId,
|
||||
drawable = GetPedDrawableVariation(ped, componentId),
|
||||
texture = GetPedTextureVariation(ped, componentId),
|
||||
}
|
||||
end
|
||||
|
||||
return components
|
||||
end
|
||||
|
||||
---@param ped number entity id
|
||||
---@return table<number, table<string, number>>
|
||||
local function getPedProps(ped)
|
||||
local size = #constants.PED_PROPS_IDS
|
||||
local props = table.create(size, 0)
|
||||
|
||||
for i = 1, size do
|
||||
local propId = constants.PED_PROPS_IDS[i]
|
||||
props[i] = {
|
||||
prop_id = propId,
|
||||
drawable = GetPedPropIndex(ped, propId),
|
||||
texture = GetPedPropTextureIndex(ped, propId),
|
||||
}
|
||||
end
|
||||
return props
|
||||
end
|
||||
|
||||
local function round(number, decimalPlaces)
|
||||
return tonumber(string.format("%." .. (decimalPlaces or 0) .. "f", number))
|
||||
end
|
||||
|
||||
---@param ped number entity id
|
||||
---@return table <number, number>
|
||||
---```
|
||||
---{ shapeFirst, shapeSecond, shapeThird, skinFirst, skinSecond, skinThird, shapeMix, skinMix, thirdMix }
|
||||
---```
|
||||
local function getPedHeadBlend(ped)
|
||||
-- GET_PED_HEAD_BLEND_DATA
|
||||
local shapeFirst, shapeSecond, shapeThird, skinFirst, skinSecond, skinThird, shapeMix, skinMix, thirdMix = Citizen.InvokeNative(0x2746BD9D88C5C5D0, ped, Citizen.PointerValueIntInitialized(0), Citizen.PointerValueIntInitialized(0), Citizen.PointerValueIntInitialized(0), Citizen.PointerValueIntInitialized(0), Citizen.PointerValueIntInitialized(0), Citizen.PointerValueIntInitialized(0), Citizen.PointerValueFloatInitialized(0), Citizen.PointerValueFloatInitialized(0), Citizen.PointerValueFloatInitialized(0))
|
||||
|
||||
shapeMix = tonumber(string.sub(shapeMix, 0, 4))
|
||||
if shapeMix > 1 then shapeMix = 1 end
|
||||
|
||||
skinMix = tonumber(string.sub(skinMix, 0, 4))
|
||||
if skinMix > 1 then skinMix = 1 end
|
||||
|
||||
if not thirdMix then
|
||||
thirdMix = 0
|
||||
end
|
||||
thirdMix = tonumber(string.sub(thirdMix, 0, 4))
|
||||
if thirdMix > 1 then thirdMix = 1 end
|
||||
|
||||
|
||||
return {
|
||||
shapeFirst = shapeFirst,
|
||||
shapeSecond = shapeSecond,
|
||||
shapeThird = shapeThird,
|
||||
skinFirst = skinFirst,
|
||||
skinSecond = skinSecond,
|
||||
skinThird = skinThird,
|
||||
shapeMix = shapeMix,
|
||||
skinMix = skinMix,
|
||||
thirdMix = thirdMix
|
||||
}
|
||||
end
|
||||
|
||||
---@param ped number entity id
|
||||
---@return table<number, table<string, number>>
|
||||
local function getPedFaceFeatures(ped)
|
||||
local size = #constants.FACE_FEATURES
|
||||
local faceFeatures = table.create(0, size)
|
||||
|
||||
for i = 1, size do
|
||||
local feature = constants.FACE_FEATURES[i]
|
||||
faceFeatures[feature] = round(GetPedFaceFeature(ped, i-1), 1)
|
||||
end
|
||||
|
||||
return faceFeatures
|
||||
end
|
||||
|
||||
---@param ped number entity id
|
||||
---@return table<number, table<string, number>>
|
||||
local function getPedHeadOverlays(ped)
|
||||
local size = #constants.HEAD_OVERLAYS
|
||||
local headOverlays = table.create(0, size)
|
||||
|
||||
for i = 1, size do
|
||||
local overlay = constants.HEAD_OVERLAYS[i]
|
||||
local _, value, _, firstColor, secondColor, opacity = GetPedHeadOverlayData(ped, i-1)
|
||||
|
||||
if value ~= 255 then
|
||||
opacity = round(opacity, 1)
|
||||
else
|
||||
value = 0
|
||||
opacity = 0
|
||||
end
|
||||
|
||||
headOverlays[overlay] = {style = value, opacity = opacity, color = firstColor, secondColor = secondColor}
|
||||
end
|
||||
|
||||
return headOverlays
|
||||
end
|
||||
|
||||
---@param ped number entity id
|
||||
---@return table<string, number>
|
||||
local function getPedHair(ped)
|
||||
return {
|
||||
style = GetPedDrawableVariation(ped, 2),
|
||||
color = GetPedHairColor(ped),
|
||||
highlight = GetPedHairHighlightColor(ped),
|
||||
texture = GetPedTextureVariation(ped, 2)
|
||||
}
|
||||
end
|
||||
|
||||
local function getPedDecorationType()
|
||||
local pedModel = GetEntityModel(cache.ped)
|
||||
local decorationType
|
||||
|
||||
if pedModel == `mp_m_freemode_01` then
|
||||
decorationType = "male"
|
||||
elseif pedModel == `mp_f_freemode_01` then
|
||||
decorationType = "female"
|
||||
else
|
||||
decorationType = IsPedMale(cache.ped) and "male" or "female"
|
||||
end
|
||||
|
||||
return decorationType
|
||||
end
|
||||
|
||||
local function getPedAppearance(ped)
|
||||
local eyeColor = GetPedEyeColor(ped)
|
||||
|
||||
return {
|
||||
model = getPedModel(ped) or "mp_m_freemode_01",
|
||||
headBlend = getPedHeadBlend(ped),
|
||||
faceFeatures = getPedFaceFeatures(ped),
|
||||
headOverlays = getPedHeadOverlays(ped),
|
||||
components = getPedComponents(ped),
|
||||
props = getPedProps(ped),
|
||||
hair = getPedHair(ped),
|
||||
tattoos = client.getPedTattoos(),
|
||||
eyeColor = eyeColor < #constants.EYE_COLORS and eyeColor or 0
|
||||
}
|
||||
end
|
||||
|
||||
local function setPlayerModel(model)
|
||||
if type(model) == "string" then model = joaat(model) end
|
||||
|
||||
if IsModelInCdimage(model) then
|
||||
RequestModel(model)
|
||||
while not HasModelLoaded(model) do Wait(0) end
|
||||
|
||||
SetPlayerModel(cache.playerId, model)
|
||||
Wait(150)
|
||||
SetModelAsNoLongerNeeded(model)
|
||||
|
||||
if isPedFreemodeModel(cache.ped) then
|
||||
SetPedDefaultComponentVariation(cache.ped)
|
||||
-- Check if the model is male or female, then change the face mix based on this.
|
||||
if model == `mp_m_freemode_01` then
|
||||
SetPedHeadBlendData(cache.ped, 0, 0, 0, 0, 0, 0, 0, 0, 0, false)
|
||||
elseif model == `mp_f_freemode_01` then
|
||||
SetPedHeadBlendData(cache.ped, 45, 21, 0, 20, 15, 0, 0.3, 0.1, 0, false)
|
||||
end
|
||||
end
|
||||
|
||||
PED_TATTOOS = {}
|
||||
return cache.ped
|
||||
end
|
||||
|
||||
return cache.playerId
|
||||
end
|
||||
|
||||
local function setPedHeadBlend(ped, headBlend)
|
||||
if headBlend and isPedFreemodeModel(ped) then
|
||||
SetPedHeadBlendData(ped, headBlend.shapeFirst, headBlend.shapeSecond, headBlend.shapeThird, headBlend.skinFirst, headBlend.skinSecond, headBlend.skinThird, tofloat(headBlend.shapeMix or 0), tofloat(headBlend.skinMix or 0), tofloat(headBlend.thirdMix or 0), false)
|
||||
end
|
||||
end
|
||||
|
||||
local function setPedFaceFeatures(ped, faceFeatures)
|
||||
if faceFeatures then
|
||||
for k, v in pairs(constants.FACE_FEATURES) do
|
||||
SetPedFaceFeature(ped, k-1, tofloat(faceFeatures[v]))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function setPedHeadOverlays(ped, headOverlays)
|
||||
if headOverlays then
|
||||
for k, v in pairs(constants.HEAD_OVERLAYS) do
|
||||
local headOverlay = headOverlays[v]
|
||||
SetPedHeadOverlay(ped, k-1, headOverlay.style, tofloat(headOverlay.opacity))
|
||||
|
||||
if headOverlay.color then
|
||||
local colorType = 1
|
||||
if v == "blush" or v == "lipstick" or v == "makeUp" then
|
||||
colorType = 2
|
||||
end
|
||||
|
||||
SetPedHeadOverlayColor(ped, k-1, colorType, headOverlay.color, headOverlay.secondColor)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function applyAutomaticFade(ped, style)
|
||||
local gender = getPedDecorationType()
|
||||
local hairDecoration = constants.HAIR_DECORATIONS[gender][style]
|
||||
|
||||
if(hairDecoration) then
|
||||
AddPedDecorationFromHashes(ped, hairDecoration[1], hairDecoration[2])
|
||||
end
|
||||
end
|
||||
|
||||
local function setTattoos(ped, tattoos, style)
|
||||
local isMale = client.getPedDecorationType() == "male"
|
||||
ClearPedDecorations(ped)
|
||||
if Config.AutomaticFade then
|
||||
tattoos["ZONE_HAIR"] = {}
|
||||
PED_TATTOOS["ZONE_HAIR"] = {}
|
||||
applyAutomaticFade(ped, style or GetPedDrawableVariation(ped, 2))
|
||||
end
|
||||
for k in pairs(tattoos) do
|
||||
for i = 1, #tattoos[k] do
|
||||
local tattoo = tattoos[k][i]
|
||||
local tattooGender = isMale and tattoo.hashMale or tattoo.hashFemale
|
||||
for _ = 1, (tattoo.opacity or 0.1) * 10 do
|
||||
AddPedDecorationFromHashes(ped, joaat(tattoo.collection), joaat(tattooGender))
|
||||
end
|
||||
end
|
||||
end
|
||||
if Config.RCoreTattoosCompatibility then
|
||||
TriggerEvent("rcore_tattoos:applyOwnedTattoos")
|
||||
end
|
||||
end
|
||||
|
||||
local function setPedHair(ped, hair, tattoos)
|
||||
if hair then
|
||||
SetPedComponentVariation(ped, 2, hair.style, hair.texture, 0)
|
||||
SetPedHairColor(ped, hair.color, hair.highlight)
|
||||
if isPedFreemodeModel(ped) then
|
||||
setTattoos(ped, tattoos or PED_TATTOOS, hair.style)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function setPedEyeColor(ped, eyeColor)
|
||||
if eyeColor then
|
||||
SetPedEyeColor(ped, eyeColor)
|
||||
end
|
||||
end
|
||||
|
||||
local function setPedComponent(ped, component)
|
||||
if component then
|
||||
if isPedFreemodeModel(ped) and (component.component_id == 0 or component.component_id == 2) then
|
||||
return
|
||||
end
|
||||
|
||||
SetPedComponentVariation(ped, component.component_id, component.drawable, component.texture, 0)
|
||||
end
|
||||
end
|
||||
|
||||
local function setPedComponents(ped, components)
|
||||
if components then
|
||||
for _, v in pairs(components) do
|
||||
setPedComponent(ped, v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function setPedProp(ped, prop)
|
||||
if prop then
|
||||
if prop.drawable == -1 then
|
||||
ClearPedProp(ped, prop.prop_id)
|
||||
else
|
||||
SetPedPropIndex(ped, prop.prop_id, prop.drawable, prop.texture, false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function setPedProps(ped, props)
|
||||
if props then
|
||||
for _, v in pairs(props) do
|
||||
setPedProp(ped, v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function setPedTattoos(ped, tattoos)
|
||||
PED_TATTOOS = tattoos
|
||||
setTattoos(ped, tattoos)
|
||||
end
|
||||
|
||||
local function getPedTattoos()
|
||||
return PED_TATTOOS
|
||||
end
|
||||
|
||||
local function addPedTattoo(ped, tattoos)
|
||||
setTattoos(ped, tattoos)
|
||||
end
|
||||
|
||||
local function removePedTattoo(ped, tattoos)
|
||||
setTattoos(ped, tattoos)
|
||||
end
|
||||
|
||||
local function setPreviewTattoo(ped, tattoos, tattoo)
|
||||
local isMale = client.getPedDecorationType() == "male"
|
||||
local tattooGender = isMale and tattoo.hashMale or tattoo.hashFemale
|
||||
|
||||
ClearPedDecorations(ped)
|
||||
for _ = 1, (tattoo.opacity or 0.1) * 10 do
|
||||
AddPedDecorationFromHashes(ped, joaat(tattoo.collection), tattooGender)
|
||||
end
|
||||
for k in pairs(tattoos) do
|
||||
for i = 1, #tattoos[k] do
|
||||
local aTattoo = tattoos[k][i]
|
||||
if aTattoo.name ~= tattoo.name then
|
||||
local aTattooGender = isMale and aTattoo.hashMale or aTattoo.hashFemale
|
||||
for _ = 1, (aTattoo.opacity or 0.1) * 10 do
|
||||
AddPedDecorationFromHashes(ped, joaat(aTattoo.collection), joaat(aTattooGender))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if Config.AutomaticFade then
|
||||
applyAutomaticFade(ped, GetPedDrawableVariation(ped, 2))
|
||||
end
|
||||
end
|
||||
|
||||
local function setPedAppearance(ped, appearance)
|
||||
if appearance then
|
||||
setPedComponents(ped, appearance.components)
|
||||
setPedProps(ped, appearance.props)
|
||||
|
||||
if appearance.headBlend and isPedFreemodeModel(ped) then setPedHeadBlend(ped, appearance.headBlend) end
|
||||
if appearance.faceFeatures then setPedFaceFeatures(ped, appearance.faceFeatures) end
|
||||
if appearance.headOverlays then setPedHeadOverlays(ped, appearance.headOverlays) end
|
||||
if appearance.hair then setPedHair(ped, appearance.hair, appearance.tattoos) end
|
||||
if appearance.eyeColor then setPedEyeColor(ped, appearance.eyeColor) end
|
||||
if appearance.tattoos then setPedTattoos(ped, appearance.tattoos) end
|
||||
end
|
||||
end
|
||||
|
||||
local function setPlayerAppearance(appearance)
|
||||
if appearance then
|
||||
setPlayerModel(appearance.model)
|
||||
setPedAppearance(cache.ped, appearance)
|
||||
end
|
||||
end
|
||||
|
||||
exports("getPedModel", getPedModel)
|
||||
exports("getPedComponents", getPedComponents)
|
||||
exports("getPedProps", getPedProps)
|
||||
exports("getPedHeadBlend", getPedHeadBlend)
|
||||
exports("getPedFaceFeatures", getPedFaceFeatures)
|
||||
exports("getPedHeadOverlays", getPedHeadOverlays)
|
||||
exports("getPedHair", getPedHair)
|
||||
exports("getPedAppearance", getPedAppearance)
|
||||
|
||||
exports("setPlayerModel", setPlayerModel)
|
||||
exports("setPedHeadBlend", setPedHeadBlend)
|
||||
exports("setPedFaceFeatures", setPedFaceFeatures)
|
||||
exports("setPedHeadOverlays", setPedHeadOverlays)
|
||||
exports("setPedHair", setPedHair)
|
||||
exports("setPedEyeColor", setPedEyeColor)
|
||||
exports("setPedComponent", setPedComponent)
|
||||
exports("setPedComponents", setPedComponents)
|
||||
exports("setPedProp", setPedProp)
|
||||
exports("setPedProps", setPedProps)
|
||||
exports("setPlayerAppearance", setPlayerAppearance)
|
||||
exports("setPedAppearance", setPedAppearance)
|
||||
exports("setPedTattoos", setPedTattoos)
|
||||
|
||||
client = {
|
||||
getPedAppearance = getPedAppearance,
|
||||
setPlayerModel = setPlayerModel,
|
||||
setPedHeadBlend = setPedHeadBlend,
|
||||
setPedFaceFeatures = setPedFaceFeatures,
|
||||
setPedHair = setPedHair,
|
||||
setPedHeadOverlays = setPedHeadOverlays,
|
||||
setPedEyeColor = setPedEyeColor,
|
||||
setPedComponent = setPedComponent,
|
||||
setPedProp = setPedProp,
|
||||
setPlayerAppearance = setPlayerAppearance,
|
||||
setPedAppearance = setPedAppearance,
|
||||
getPedDecorationType = getPedDecorationType,
|
||||
isPedFreemodeModel = isPedFreemodeModel,
|
||||
setPreviewTattoo = setPreviewTattoo,
|
||||
setPedTattoos = setPedTattoos,
|
||||
getPedTattoos = getPedTattoos,
|
||||
addPedTattoo = addPedTattoo,
|
||||
removePedTattoo = removePedTattoo,
|
||||
getPedModel = getPedModel,
|
||||
setPedComponents = setPedComponents,
|
||||
setPedProps = setPedProps,
|
||||
getPedComponents = getPedComponents,
|
||||
getPedProps = getPedProps
|
||||
}
|
367
resources/[il]/illenium-appearance/locales/da.lua
Normal file
@ -0,0 +1,367 @@
|
||||
Locales["da"] = {
|
||||
UI = {
|
||||
modal = {
|
||||
save = {
|
||||
title = "Gem ændringer!",
|
||||
description = "Ikke at du bliver kønnere, men ja..."
|
||||
},
|
||||
exit = {
|
||||
title = "Glem ændringer",
|
||||
description = "Du forbliver grim"
|
||||
},
|
||||
accept = "Ja",
|
||||
decline = "Nej"
|
||||
},
|
||||
ped = {
|
||||
title = "Ped",
|
||||
model = "Model"
|
||||
},
|
||||
headBlend = {
|
||||
title = "Oprindelse",
|
||||
shape = {
|
||||
title = "Ansigt",
|
||||
firstOption = "Far",
|
||||
secondOption = "Mor",
|
||||
mix = "Mix"
|
||||
},
|
||||
skin = {
|
||||
title = "Hud",
|
||||
firstOption = "Far",
|
||||
secondOption = "Mor",
|
||||
mix = "Mix"
|
||||
},
|
||||
race = {
|
||||
title = "Race",
|
||||
shape = "Form",
|
||||
skin = "Hud",
|
||||
mix = "Mix"
|
||||
}
|
||||
},
|
||||
faceFeatures = {
|
||||
title = "Ansigtstræk",
|
||||
nose = {
|
||||
title = "Næse",
|
||||
width = "Bredde",
|
||||
height = "Højde",
|
||||
size = "Størrelse",
|
||||
boneHeight = "Benhøjde",
|
||||
boneTwist = "Krumning",
|
||||
peakHeight = "Næsespidshøjde"
|
||||
},
|
||||
eyebrows = {
|
||||
title = "Øjenbryn",
|
||||
height = "Højde",
|
||||
depth = "Dybde",
|
||||
},
|
||||
cheeks = {
|
||||
title = "Kinder",
|
||||
boneHeight = "Benhøjde",
|
||||
boneWidth = "Knoglebens bredde",
|
||||
width = "Bredde"
|
||||
},
|
||||
eyesAndMouth = {
|
||||
title = "Øjne og mund",
|
||||
eyesOpening = "Øjenåbning",
|
||||
lipsThickness = "Læber tykkelse"
|
||||
},
|
||||
jaw = {
|
||||
title = "Kæbe",
|
||||
width = "Bredde",
|
||||
size = "Størrelse"
|
||||
},
|
||||
chin = {
|
||||
title = "Hage",
|
||||
lowering = "Sænkning",
|
||||
length = "Længde",
|
||||
size = "Størrelse",
|
||||
hole = "Kløftstørrelse"
|
||||
},
|
||||
neck = {
|
||||
title = "Hals",
|
||||
thickness = "Tykkelse"
|
||||
}
|
||||
},
|
||||
headOverlays = {
|
||||
title = "Udseende",
|
||||
hair = {
|
||||
title = "Hår",
|
||||
style = "Stil",
|
||||
color = "Farve",
|
||||
highlight = "Highlight",
|
||||
texture = "Tekstur",
|
||||
fade = "Fade"
|
||||
},
|
||||
opacity = "Gennemsigtighed",
|
||||
style = "Stil",
|
||||
color = "Farve",
|
||||
secondColor = "Anden farve",
|
||||
blemishes = "Urenheder",
|
||||
beard = "Skæg",
|
||||
eyebrows = "Øjenbryn",
|
||||
ageing = "Aldring",
|
||||
makeUp = "Makeup",
|
||||
blush = "Blush",
|
||||
complexion = "Kompleksion",
|
||||
sunDamage = "Solskader",
|
||||
lipstick = "Læbestift",
|
||||
moleAndFreckles = "Fødselsmærker og fregner",
|
||||
chestHair = "Brysthår",
|
||||
bodyBlemishes = "Kropsurenheder",
|
||||
eyeColor = "Øjenfarve",
|
||||
},
|
||||
components = {
|
||||
title = "Tøj",
|
||||
drawable = "Variant",
|
||||
texture = "Tekstur",
|
||||
mask = "Masker",
|
||||
upperBody = "Overkrop",
|
||||
lowerBody = "Underkrop",
|
||||
bags = "Tasker og faldskærme",
|
||||
shoes = "Sko",
|
||||
scarfAndChains = "Hals-tilbehør",
|
||||
shirt = "Trøjer",
|
||||
bodyArmor = "Kropsbeskyttelse",
|
||||
decals = "Mærkater",
|
||||
jackets = "Jakker",
|
||||
head = "Hoved",
|
||||
},
|
||||
props = {
|
||||
title = "Tilbehør",
|
||||
drawable = "Variant",
|
||||
texture = "Tekstur",
|
||||
hats = "Hovedbeklædning",
|
||||
glasses = "Briller",
|
||||
ear = "Øre",
|
||||
watches = "Ure",
|
||||
bracelets = "Armbånd"
|
||||
},
|
||||
tattoos = {
|
||||
title = "Tatoveringer",
|
||||
items = {
|
||||
ZONE_TORSO = "Overkrop",
|
||||
ZONE_HEAD = "Hoved",
|
||||
ZONE_LEFT_ARM = "Venstre arm",
|
||||
ZONE_RIGHT_ARM = "Højre arm",
|
||||
ZONE_LEFT_LEG = "Venstre ben",
|
||||
ZONE_RIGHT_LEG = "Højre ben",
|
||||
},
|
||||
apply = "Tilføj",
|
||||
delete = "Fjern",
|
||||
deleteAll = "Fjern alle",
|
||||
opacity = "Gennemsigtighed"
|
||||
}
|
||||
},
|
||||
outfitManagement = {
|
||||
title = "Outfit håndtering",
|
||||
jobText = "Håndter outfits for job",
|
||||
gangText = "Håndter outfits for bande",
|
||||
},
|
||||
cancelled = {
|
||||
title = "Annulleret",
|
||||
description = "Handlingen blev annulleret"
|
||||
},
|
||||
outfits = {
|
||||
import = {
|
||||
title = "Indtast outfit kode",
|
||||
menuTitle = "Importer outfit fra kode",
|
||||
description = "Importer et outfit fra en share-code",
|
||||
name = {
|
||||
label = "Outfit navn",
|
||||
placeholder = "Swagger",
|
||||
default = "Importeret outfit"
|
||||
},
|
||||
code = {
|
||||
label = "Outfit kode",
|
||||
},
|
||||
success = {
|
||||
title = "Outfit importeret",
|
||||
description = "Du kan nu skifte til outfittet ved at bruge outfit menuen"
|
||||
},
|
||||
failure = {
|
||||
title = "Noget gik galt",
|
||||
description = "Ugyldig outfit kode"
|
||||
}
|
||||
},
|
||||
generate = {
|
||||
title = "Generer outfit kode",
|
||||
description = "Generer en share-code for dit nuværende outfit",
|
||||
failure = {
|
||||
title = "Noget gik galt",
|
||||
description = "Kunne ikke generere outfit kode"
|
||||
},
|
||||
success = {
|
||||
title = "Outfit kode genereret",
|
||||
description = "Her er din outfit kode"
|
||||
}
|
||||
},
|
||||
save = {
|
||||
menuTitle = "Gem nuværende outfit",
|
||||
menuDescription = "Gem dit nuværende outfit som %s outfit",
|
||||
description = "Gem dit nuværende outfit",
|
||||
title = "Navngiv dit outfit",
|
||||
managementTitle = "Håndter outfit detaljer",
|
||||
name = {
|
||||
label = "Outfit navn",
|
||||
placeholder = "Swagger",
|
||||
},
|
||||
gender = {
|
||||
label = "Køn",
|
||||
male = "Mand",
|
||||
female = "Kvinde"
|
||||
},
|
||||
rank = {
|
||||
label = "Minimum grad"
|
||||
},
|
||||
failure = {
|
||||
title = "Noget gik galt",
|
||||
description = "Outfit med dette navn findes allerede"
|
||||
},
|
||||
success = {
|
||||
title = "Outfit gemt",
|
||||
description = "Outfit %s blev gemt"
|
||||
}
|
||||
},
|
||||
update = {
|
||||
title = "Opdater outfit",
|
||||
description = "Opdater dit nuværende outfit til et eksisterende outfit",
|
||||
failure = {
|
||||
title = "Noget gik galt",
|
||||
description = "Outfittet eksisterer ikke"
|
||||
},
|
||||
success = {
|
||||
title = "Outfit opdateret",
|
||||
description = "Outfit %s blev opdateret"
|
||||
}
|
||||
},
|
||||
change = {
|
||||
title = "Skift outfit",
|
||||
description = "Skift til et af dine %s outfits",
|
||||
pDescription = "Vælg et af dine gemte outfits",
|
||||
failure = {
|
||||
title = "Noget gik galt",
|
||||
description = "Det outfit du prøver at skifte til, har ikke et grund-udseende",
|
||||
}
|
||||
},
|
||||
delete = {
|
||||
title = "Slet outfit",
|
||||
description = "Slet et gemt %s outfit",
|
||||
mDescription = "Slet et af dine gemte outfits",
|
||||
item = {
|
||||
title = 'Slet "%s"',
|
||||
description = "Model: %s%s"
|
||||
},
|
||||
success = {
|
||||
title = "Outflit slettet",
|
||||
description = "Det valgte outfit blev slettet"
|
||||
}
|
||||
},
|
||||
manage = {
|
||||
title = "👔 | Håndter %s outfits"
|
||||
}
|
||||
},
|
||||
jobOutfits = {
|
||||
title = "Arbejdstøj",
|
||||
description = "Skift til et sæt arbejdstøj",
|
||||
},
|
||||
menu = {
|
||||
returnTitle = "Tilbage",
|
||||
title = "Skifterum",
|
||||
outfitsTitle = "Spiller outfits",
|
||||
clothingShopTitle = "Tøkbutik",
|
||||
barberShopTitle = "Frisør",
|
||||
tattooShopTitle = "Tatovør",
|
||||
surgeonShopTitle = "Plastikkirurg",
|
||||
},
|
||||
clothing = {
|
||||
title = "Køb tøj - %d,-",
|
||||
titleNoPrice = "Skift tøj",
|
||||
options = {
|
||||
title = "👔 | Tøjbutik muligheder",
|
||||
description = "Vælg fra et bredt udvalg af tøj"
|
||||
},
|
||||
outfits = {
|
||||
title = "👔 | Outfit muligheder",
|
||||
civilian = {
|
||||
title = "Civilt tøj",
|
||||
description = "Tag tøj på"
|
||||
}
|
||||
}
|
||||
},
|
||||
commands = {
|
||||
reloadskin = {
|
||||
title = "Genindlæser din karakter",
|
||||
failure = {
|
||||
title = "Noget gik galt",
|
||||
description = "Du kan ikke bruge reloadskin lige nu"
|
||||
}
|
||||
},
|
||||
clearstuckprops = {
|
||||
title = "Fjerner alle props fra din karakter",
|
||||
failure = {
|
||||
title = "Noget gik galt",
|
||||
description = "Du kan ikke bruge clearstuckprops lige nu"
|
||||
}
|
||||
},
|
||||
pedmenu = {
|
||||
title = "Åben / Giv tøj menuen",
|
||||
failure = {
|
||||
title = "Noget gik galt",
|
||||
description = "Spilleren er ikke online"
|
||||
}
|
||||
},
|
||||
joboutfits = {
|
||||
title = "Åben arbedstøj menu"
|
||||
},
|
||||
gangoutfits = {
|
||||
title = "Åben bandetøj menu"
|
||||
},
|
||||
bossmanagedoutfits = {
|
||||
title = "Åben chef outfit menu"
|
||||
}
|
||||
},
|
||||
textUI = {
|
||||
clothing = "Tøjbutik - Pris: %d,-",
|
||||
barber = "Frisør - Pris: %d,-",
|
||||
tattoo = "Tatovør - Pris: %d,-",
|
||||
surgeon = "Plastikkirurg - Pris: %d,-",
|
||||
clothingRoom = "Omklædningsrum",
|
||||
playerOutfitRoom = "Outfits"
|
||||
},
|
||||
migrate = {
|
||||
success = {
|
||||
title = "Success",
|
||||
description = "Migrering færdig. %s skins migreret",
|
||||
descriptionSingle = "Migrer skin"
|
||||
},
|
||||
skip = {
|
||||
title = "Information",
|
||||
description = "Sprang skin over"
|
||||
},
|
||||
typeError = {
|
||||
title = "Noget gik galt",
|
||||
description = "Ugyldig type"
|
||||
}
|
||||
},
|
||||
purchase = {
|
||||
tattoo = {
|
||||
success = {
|
||||
title = "Success",
|
||||
description = "Købte %s tatovering for %s,-"
|
||||
},
|
||||
failure = {
|
||||
title = "Kunne ikke tatovere",
|
||||
description = "Du har ikke råd..."
|
||||
}
|
||||
},
|
||||
store = {
|
||||
success = {
|
||||
title = "Success",
|
||||
description = "Købte %s for %s,-"
|
||||
},
|
||||
failure = {
|
||||
title = "Tyveri!",
|
||||
description = "Du havde ikke nok penge! Du prøvede nok at stjæle, hva?"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
17
resources/[il]/illenium-appearance/locales/locales.lua
Normal file
@ -0,0 +1,17 @@
|
||||
Locales = {}
|
||||
|
||||
function _L(key)
|
||||
local lang = GetConvar("illenium-appearance:locale", "da")
|
||||
if not Locales[lang] then
|
||||
lang = "da"
|
||||
end
|
||||
local value = Locales[lang]
|
||||
for k in key:gmatch("[^.]+") do
|
||||
value = value[k]
|
||||
if not value then
|
||||
print("Missing locale for: " .. key)
|
||||
return ""
|
||||
end
|
||||
end
|
||||
return value
|
||||
end
|
@ -0,0 +1 @@
|
||||
Database = {}
|
@ -0,0 +1,5 @@
|
||||
Database.JobGrades = {}
|
||||
|
||||
function Database.JobGrades.GetByJobName(name)
|
||||
return MySQL.query.await("SELECT grade,name,label FROM job_grades WHERE job_name = ?", {name})
|
||||
end
|
@ -0,0 +1,30 @@
|
||||
Database.ManagementOutfits = {}
|
||||
|
||||
function Database.ManagementOutfits.GetAllByJob(type, jobName, gender)
|
||||
local query = "SELECT * FROM management_outfits WHERE type = ? AND job_name = ?"
|
||||
local queryArgs = {type, jobName}
|
||||
|
||||
if gender then
|
||||
query = query .. " AND gender = ?"
|
||||
queryArgs[#queryArgs + 1] = gender
|
||||
end
|
||||
|
||||
return MySQL.query.await(query, queryArgs)
|
||||
end
|
||||
|
||||
function Database.ManagementOutfits.Add(outfitData)
|
||||
return MySQL.insert.await("INSERT INTO management_outfits (job_name, type, minrank, name, gender, model, props, components) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", {
|
||||
outfitData.JobName,
|
||||
outfitData.Type,
|
||||
outfitData.MinRank,
|
||||
outfitData.Name,
|
||||
outfitData.Gender,
|
||||
outfitData.Model,
|
||||
json.encode(outfitData.Props),
|
||||
json.encode(outfitData.Components)
|
||||
})
|
||||
end
|
||||
|
||||
function Database.ManagementOutfits.DeleteByID(id)
|
||||
MySQL.query.await("DELETE FROM management_outfits WHERE id = ?", {id})
|
||||
end
|
@ -0,0 +1,17 @@
|
||||
Database.PlayerOutfitCodes = {}
|
||||
|
||||
function Database.PlayerOutfitCodes.GetByCode(code)
|
||||
return MySQL.single.await("SELECT * FROM player_outfit_codes WHERE code = ?", {code})
|
||||
end
|
||||
|
||||
function Database.PlayerOutfitCodes.GetByOutfitID(outfitID)
|
||||
return MySQL.single.await("SELECT * FROM player_outfit_codes WHERE outfitID = ?", {outfitID})
|
||||
end
|
||||
|
||||
function Database.PlayerOutfitCodes.Add(outfitID, code)
|
||||
return MySQL.insert.await("INSERT INTO player_outfit_codes (outfitid, code) VALUES (?, ?)", {outfitID, code})
|
||||
end
|
||||
|
||||
function Database.PlayerOutfitCodes.DeleteByOutfitID(id)
|
||||
MySQL.query.await("DELETE FROM player_outfit_codes WHERE outfitid = ?", {id})
|
||||
end
|
@ -0,0 +1,36 @@
|
||||
Database.PlayerOutfits = {}
|
||||
|
||||
function Database.PlayerOutfits.GetAllByCitizenID(citizenid)
|
||||
return MySQL.query.await("SELECT * FROM player_outfits WHERE citizenid = ?", {citizenid})
|
||||
end
|
||||
|
||||
function Database.PlayerOutfits.GetByID(id)
|
||||
return MySQL.single.await("SELECT * FROM player_outfits WHERE id = ?", {id})
|
||||
end
|
||||
|
||||
function Database.PlayerOutfits.GetByOutfit(name, citizenid) -- for validate duplicate name before insert
|
||||
return MySQL.single.await("SELECT * FROM player_outfits WHERE outfitname = ? AND citizenid = ?", {name, citizenid})
|
||||
end
|
||||
|
||||
function Database.PlayerOutfits.Add(citizenID, outfitName, model, components, props)
|
||||
return MySQL.insert.await("INSERT INTO player_outfits (citizenid, outfitname, model, components, props) VALUES (?, ?, ?, ?, ?)", {
|
||||
citizenID,
|
||||
outfitName,
|
||||
model,
|
||||
components,
|
||||
props
|
||||
})
|
||||
end
|
||||
|
||||
function Database.PlayerOutfits.Update(outfitID, model, components, props)
|
||||
return MySQL.update.await("UPDATE player_outfits SET model = ?, components = ?, props = ? WHERE id = ?", {
|
||||
model,
|
||||
components,
|
||||
props,
|
||||
outfitID
|
||||
})
|
||||
end
|
||||
|
||||
function Database.PlayerOutfits.DeleteByID(id)
|
||||
MySQL.query.await("DELETE FROM player_outfits WHERE id = ?", {id})
|
||||
end
|
@ -0,0 +1,5 @@
|
||||
Database.Players = {}
|
||||
|
||||
function Database.Players.GetAll()
|
||||
return MySQL.query.await("SELECT * FROM players")
|
||||
end
|
@ -0,0 +1,34 @@
|
||||
Database.PlayerSkins = {}
|
||||
|
||||
function Database.PlayerSkins.UpdateActiveField(citizenID, active)
|
||||
MySQL.update.await("UPDATE playerskins SET active = ? WHERE citizenid = ?", {active, citizenID}) -- Make all the skins inactive / active
|
||||
end
|
||||
|
||||
function Database.PlayerSkins.DeleteByModel(citizenID, model)
|
||||
MySQL.query.await("DELETE FROM playerskins WHERE citizenid = ? AND model = ?", {citizenID, model})
|
||||
end
|
||||
|
||||
function Database.PlayerSkins.Add(citizenID, model, appearance, active)
|
||||
MySQL.insert.await("INSERT INTO playerskins (citizenid, model, skin, active) VALUES (?, ?, ?, ?)", {citizenID, model, appearance, active})
|
||||
end
|
||||
|
||||
function Database.PlayerSkins.GetByCitizenID(citizenID, model)
|
||||
local query = "SELECT skin FROM playerskins WHERE citizenid = ?"
|
||||
local queryArgs = {citizenID}
|
||||
if model ~= nil then
|
||||
query = query .. " AND model = ?"
|
||||
queryArgs[#queryArgs + 1] = model
|
||||
else
|
||||
query = query .. " AND active = ?"
|
||||
queryArgs[#queryArgs + 1] = 1
|
||||
end
|
||||
return MySQL.scalar.await(query, queryArgs)
|
||||
end
|
||||
|
||||
function Database.PlayerSkins.DeleteByCitizenID(citizenID)
|
||||
MySQL.query.await("DELETE FROM playerskins WHERE citizenid = ?", { citizenID })
|
||||
end
|
||||
|
||||
function Database.PlayerSkins.GetAll()
|
||||
return MySQL.query.await("SELECT * FROM playerskins")
|
||||
end
|
13
resources/[il]/illenium-appearance/server/database/users.lua
Normal file
@ -0,0 +1,13 @@
|
||||
Database.Users = {}
|
||||
|
||||
function Database.Users.UpdateSkinForUser(citizenID, skin)
|
||||
return MySQL.update.await("UPDATE users SET skin = ? WHERE identifier = ?", {skin, citizenID})
|
||||
end
|
||||
|
||||
function Database.Users.GetSkinByCitizenID(citizenID)
|
||||
return MySQL.single.await("SELECT skin FROM users WHERE identifier = ?", {citizenID})
|
||||
end
|
||||
|
||||
function Database.Users.GetAll()
|
||||
return MySQL.query.await("SELECT * FROM users")
|
||||
end
|
@ -0,0 +1,18 @@
|
||||
if not Framework.ESX() then return end
|
||||
|
||||
local ESX = exports["es_extended"]:getSharedObject()
|
||||
|
||||
ESX.RegisterServerCallback("esx_skin:getPlayerSkin", function(source, cb)
|
||||
local Player = ESX.GetPlayerFromId(source)
|
||||
|
||||
local appearance = Framework.GetAppearance(Player.identifier)
|
||||
|
||||
cb(appearance, {
|
||||
skin_male = Player.job.skin_male,
|
||||
skin_female = Player.job.skin_female
|
||||
})
|
||||
end)
|
||||
|
||||
lib.callback.register("illenium-appearance:server:esx:getGradesForJob", function(_, jobName)
|
||||
return Database.JobGrades.GetByJobName(jobName)
|
||||
end)
|
@ -0,0 +1,63 @@
|
||||
if not Framework.ESX() then return end
|
||||
|
||||
local ESX = exports["es_extended"]:getSharedObject()
|
||||
|
||||
function Framework.GetPlayerID(src)
|
||||
local Player = ESX.GetPlayerFromId(src)
|
||||
if Player then
|
||||
return Player.identifier
|
||||
end
|
||||
end
|
||||
|
||||
function Framework.HasMoney(src, type, money)
|
||||
if type == "cash" then
|
||||
type = "money"
|
||||
end
|
||||
local Player = ESX.GetPlayerFromId(src)
|
||||
return Player.getAccount(type).money >= money
|
||||
end
|
||||
|
||||
function Framework.RemoveMoney(src, type, money)
|
||||
if type == "cash" then
|
||||
type = "money"
|
||||
end
|
||||
local Player = ESX.GetPlayerFromId(src)
|
||||
if Player.getAccount(type).money >= money then
|
||||
Player.removeAccountMoney(type, money)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function normalizeGrade(job)
|
||||
job.grade = {
|
||||
level = job.grade
|
||||
}
|
||||
return job
|
||||
end
|
||||
|
||||
function Framework.GetJob(src)
|
||||
local Player = ESX.GetPlayerFromId(src)
|
||||
return normalizeGrade(Player.getJob())
|
||||
end
|
||||
|
||||
function Framework.GetGang(src)
|
||||
local Player = ESX.GetPlayerFromId(src)
|
||||
return normalizeGrade(Player.getJob())
|
||||
end
|
||||
|
||||
function Framework.SaveAppearance(appearance, citizenID)
|
||||
Database.Users.UpdateSkinForUser(citizenID, json.encode(appearance))
|
||||
end
|
||||
|
||||
function Framework.GetAppearance(citizenID)
|
||||
local user = Database.Users.GetSkinByCitizenID(citizenID)
|
||||
if user then
|
||||
local skin = json.decode(user.skin)
|
||||
if skin then
|
||||
skin.sex = skin.model == "mp_m_freemode_01" and 0 or 1
|
||||
return skin
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
@ -0,0 +1,28 @@
|
||||
if not Framework.ESX() then return end
|
||||
|
||||
if Config.BossManagedOutfits then
|
||||
function isBoss(grades, grade)
|
||||
local highestGrade = grades[1].grade
|
||||
for i = 2, #grades do
|
||||
if grades[i].grade > highestGrade then
|
||||
highestGrade = grades[i].grade
|
||||
end
|
||||
end
|
||||
return highestGrade == grade
|
||||
end
|
||||
lib.addCommand("bossmanagedoutfits", { help = _L("commands.bossmanagedoutfits.title"), }, function(source)
|
||||
local job = Framework.GetJob(source)
|
||||
local grades = Database.JobGrades.GetByJobName(job.name)
|
||||
if not grades then
|
||||
return
|
||||
end
|
||||
|
||||
if not isBoss(grades, job.grade.level) then
|
||||
return
|
||||
end
|
||||
|
||||
TriggerClientEvent("illenium-appearance:client:OutfitManagementMenu", source, {
|
||||
type = "Job"
|
||||
})
|
||||
end)
|
||||
end
|
@ -0,0 +1,156 @@
|
||||
if not Framework.ESX() then return end
|
||||
|
||||
local function tofloat(num)
|
||||
return num + 0.0
|
||||
end
|
||||
|
||||
local function convertSkinToNewFormat(oldSkin, gender)
|
||||
local skin = {
|
||||
components = Framework.ConvertComponents(oldSkin),
|
||||
eyeColor = oldSkin.eye_color,
|
||||
faceFeatures = {
|
||||
chinBoneLenght = tofloat((oldSkin.chin_2 or 0) / 10),
|
||||
noseBoneTwist = tofloat((oldSkin.nose_6 or 0) / 10),
|
||||
nosePeakHigh = tofloat((oldSkin.nose_2 or 0) / 10),
|
||||
jawBoneWidth = tofloat((oldSkin.jaw_1 or 0) / 10),
|
||||
cheeksWidth = tofloat((oldSkin.cheeks_3 or 0) / 10),
|
||||
eyeBrownHigh = tofloat((oldSkin.eyebrows_5 or 0) / 10),
|
||||
chinHole = tofloat((oldSkin.chin_4 or 0) / 10),
|
||||
jawBoneBackSize = tofloat((oldSkin.jaw_2 or 0) / 10),
|
||||
eyesOpening = tofloat((oldSkin.eye_squint or 0) / 10),
|
||||
lipsThickness = tofloat((oldSkin.lip_thickness or 0) / 10),
|
||||
nosePeakSize = tofloat((oldSkin.nose_3 or 0) / 10),
|
||||
eyeBrownForward = tofloat((oldSkin.eyebrows_6 or 0) / 10),
|
||||
neckThickness = tofloat((oldSkin.neck_thickness or 0) / 10),
|
||||
chinBoneSize = tofloat((oldSkin.chin_3 or 0) / 10),
|
||||
chinBoneLowering = tofloat((oldSkin.chin_1 or 0) / 10),
|
||||
cheeksBoneWidth = tofloat((oldSkin.cheeks_2 or 0) / 10),
|
||||
nosePeakLowering = tofloat((oldSkin.nose_5 or 0) / 10),
|
||||
noseBoneHigh = tofloat((oldSkin.nose_4 or 0) / 10),
|
||||
cheeksBoneHigh = tofloat((oldSkin.cheeks_1 or 0) / 10),
|
||||
noseWidth = tofloat((oldSkin.nose_1 or 0) / 10)
|
||||
},
|
||||
hair = {
|
||||
highlight = oldSkin.hair_color_2 or 0,
|
||||
texture = oldSkin.hair_2 or 0,
|
||||
style = oldSkin.hair_1 or 0,
|
||||
color = oldSkin.hair_color_1 or 0
|
||||
},
|
||||
headBlend = {
|
||||
thirdMix = 0,
|
||||
skinSecond = oldSkin.dad or 0,
|
||||
skinMix = tofloat((oldSkin.skin_md_weight or 0) / 100),
|
||||
skinThird = 0,
|
||||
shapeFirst = oldSkin.mom or 0,
|
||||
shapeThird = 0,
|
||||
shapeMix = tofloat((oldSkin.face_md_weight or 0) / 100),
|
||||
shapeSecond = oldSkin.dad or 0,
|
||||
skinFirst = oldSkin.mom or 0
|
||||
},
|
||||
headOverlays = {
|
||||
complexion = {
|
||||
opacity = tofloat((oldSkin.complexion_2 or 0) / 10),
|
||||
color = 0,
|
||||
style = oldSkin.complexion_1 or 0,
|
||||
secondColor = 0
|
||||
},
|
||||
lipstick = {
|
||||
opacity = tofloat((oldSkin.lipstick_2 or 0) / 10),
|
||||
color = oldSkin.lipstick_3 or 0,
|
||||
style = oldSkin.lipstick_1 or 0,
|
||||
secondColor = oldSkin.lipstick_4 or 0
|
||||
},
|
||||
eyebrows = {
|
||||
opacity = tofloat((oldSkin.eyebrows_2 or 0) / 10),
|
||||
color = oldSkin.eyebrows_3 or 0,
|
||||
style = oldSkin.eyebrows_1 or 0,
|
||||
secondColor = oldSkin.eyebrows_4 or 0
|
||||
},
|
||||
beard = {
|
||||
opacity = tofloat((oldSkin.beard_2 or 0) / 10),
|
||||
color = oldSkin.beard_3 or 0,
|
||||
style = oldSkin.beard_1 or 0,
|
||||
secondColor = oldSkin.beard_4 or 0
|
||||
},
|
||||
blush = {
|
||||
opacity = tofloat((oldSkin.blush_2 or 0) / 10),
|
||||
color = oldSkin.blush_3 or 0,
|
||||
style = oldSkin.blush_1 or 0,
|
||||
secondColor = oldSkin.blush_4 or 0
|
||||
},
|
||||
ageing = {
|
||||
opacity = tofloat((oldSkin.age_2 or 0) / 10),
|
||||
color = 0,
|
||||
style = oldSkin.age_1 or 0,
|
||||
secondColor = 0
|
||||
},
|
||||
blemishes = {
|
||||
opacity = tofloat((oldSkin.blemishes_2 or 0) / 10),
|
||||
color = 0,
|
||||
style = oldSkin.blemishes_1 or 0,
|
||||
secondColor = 0
|
||||
},
|
||||
chestHair = {
|
||||
opacity = tofloat((oldSkin.chest_2 or 0) / 10),
|
||||
color = oldSkin.chest_3 or 0,
|
||||
style = oldSkin.chest_1 or 0,
|
||||
secondColor = 0
|
||||
},
|
||||
bodyBlemishes = {
|
||||
opacity = tofloat((oldSkin.bodyb_2 or 0) / 10),
|
||||
color = oldSkin.bodyb_3 or 0,
|
||||
style = oldSkin.bodyb_1 or 0,
|
||||
secondColor = oldSkin.bodyb_4 or 0
|
||||
},
|
||||
moleAndFreckles = {
|
||||
opacity = tofloat((oldSkin.moles_2 or 0) / 10),
|
||||
color = 0,
|
||||
style = oldSkin.moles_1 or 0,
|
||||
secondColor = 0
|
||||
},
|
||||
sunDamage = {
|
||||
opacity = tofloat((oldSkin.sun_2 or 0) / 10),
|
||||
color = 0,
|
||||
style = oldSkin.sun_1 or 0,
|
||||
secondColor = 0
|
||||
},
|
||||
makeUp = {
|
||||
opacity = tofloat((oldSkin.makeup_2 or 0) / 10),
|
||||
color = oldSkin.makeup_3 or 0,
|
||||
style = oldSkin.makeup_1 or 0,
|
||||
secondColor = oldSkin.makeup_4 or 0
|
||||
}
|
||||
},
|
||||
model = gender == "m" and "mp_m_freemode_01" or "mp_f_freemode_01",
|
||||
props = Framework.ConvertProps(oldSkin),
|
||||
tattoos = {}
|
||||
}
|
||||
|
||||
return skin
|
||||
end
|
||||
|
||||
lib.addCommand("migrateskins", { help = "Migrate skins", restricted = "group.admin" }, function(source)
|
||||
local users = Database.Users.GetAll()
|
||||
local convertedSkins = 0
|
||||
if users then
|
||||
for i = 1, #users do
|
||||
local user = users[i]
|
||||
if user.skin then
|
||||
local oldSkin = json.decode(user.skin)
|
||||
if oldSkin.hair_1 then -- Convert only if its an old skin
|
||||
local skin = json.encode(convertSkinToNewFormat(oldSkin, user.sex))
|
||||
local affectedRows = Database.Users.UpdateSkinForUser(user.identifier, skin)
|
||||
if affectedRows then
|
||||
convertedSkins += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
lib.notify(source, {
|
||||
title = _L("migrate.success.title"),
|
||||
description = string.format(_L("migrate.success.description"), tostring(convertedSkins)),
|
||||
type = "success",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
end)
|
@ -0,0 +1,43 @@
|
||||
if not Framework.QBCore() then return end
|
||||
|
||||
local QBCore = exports["qb-core"]:GetCoreObject()
|
||||
|
||||
function Framework.GetPlayerID(src)
|
||||
local Player = QBCore.Functions.GetPlayer(src)
|
||||
if Player then
|
||||
return Player.PlayerData.citizenid
|
||||
end
|
||||
end
|
||||
|
||||
function Framework.HasMoney(src, type, money)
|
||||
local Player = QBCore.Functions.GetPlayer(src)
|
||||
return Player.PlayerData.money[type] >= money
|
||||
end
|
||||
|
||||
function Framework.RemoveMoney(src, type, money)
|
||||
local Player = QBCore.Functions.GetPlayer(src)
|
||||
return Player.Functions.RemoveMoney(type, money)
|
||||
end
|
||||
|
||||
function Framework.GetJob(src)
|
||||
local Player = QBCore.Functions.GetPlayer(src)
|
||||
return Player.PlayerData.job
|
||||
end
|
||||
|
||||
function Framework.GetGang(src)
|
||||
local Player = QBCore.Functions.GetPlayer(src)
|
||||
return Player.PlayerData.gang
|
||||
end
|
||||
|
||||
function Framework.SaveAppearance(appearance, citizenID)
|
||||
Database.PlayerSkins.UpdateActiveField(citizenID, 0)
|
||||
Database.PlayerSkins.DeleteByModel(citizenID, appearance.model)
|
||||
Database.PlayerSkins.Add(citizenID, appearance.model, json.encode(appearance), 1)
|
||||
end
|
||||
|
||||
function Framework.GetAppearance(citizenID, model)
|
||||
local result = Database.PlayerSkins.GetByCitizenID(citizenID, model)
|
||||
if result then
|
||||
return json.decode(result)
|
||||
end
|
||||
end
|
@ -0,0 +1,97 @@
|
||||
if not Framework.QBCore() then return end
|
||||
|
||||
local continue = false
|
||||
|
||||
local function MigrateFivemAppearance(source)
|
||||
local allPlayers = Database.Players.GetAll()
|
||||
local playerSkins = {}
|
||||
for i=1, #allPlayers, 1 do
|
||||
if allPlayers[i].skin then
|
||||
playerSkins[#playerSkins+1] = {
|
||||
citizenID = allPlayers[i].citizenid,
|
||||
skin = allPlayers[i].skin
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
for i=1, #playerSkins, 1 do
|
||||
Database.PlayerSkins.Add(playerSkins[i].citizenID, json.decode(playerSkins[i].skin).model, playerSkins[i].skin, 1)
|
||||
end
|
||||
lib.notify(source, {
|
||||
title = _L("migrate.success.title"),
|
||||
description = string.format(_L("migrate.success.description"), tostring(#playerSkins)),
|
||||
type = "success",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
end
|
||||
|
||||
local function MigrateQBClothing(source)
|
||||
local allPlayerSkins = Database.PlayerSkins.GetAll()
|
||||
local migrated = 0
|
||||
for i=1, #allPlayerSkins, 1 do
|
||||
if not tonumber(allPlayerSkins[i].model) then
|
||||
lib.notify(source, {
|
||||
title = _L("migrate.skip.title"),
|
||||
description = _L("migrate.skip.description"),
|
||||
type = "inform",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
else
|
||||
TriggerClientEvent("illenium-appearance:client:migration:load-qb-clothing-skin", source, allPlayerSkins[i])
|
||||
while not continue do
|
||||
Wait(10)
|
||||
end
|
||||
continue = false
|
||||
migrated = migrated + 1
|
||||
end
|
||||
end
|
||||
TriggerClientEvent("illenium-appearance:client:reloadSkin", source)
|
||||
|
||||
lib.notify(source, {
|
||||
title = _L("migrate.success.title"),
|
||||
description = string.format(_L("migrate.success.description"), tostring(migrated)),
|
||||
type = "success",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
end
|
||||
|
||||
RegisterNetEvent("illenium-appearance:server:migrate-qb-clothing-skin", function(citizenid, appearance)
|
||||
local src = source
|
||||
Database.PlayerSkins.DeleteByCitizenID(citizenid)
|
||||
Database.PlayerSkins.Add(citizenid, appearance.model, json.encode(appearance), 1)
|
||||
continue = true
|
||||
lib.notify(src, {
|
||||
id = "illenium_appearance_skin_migrated",
|
||||
title = _L("migrate.success.title"),
|
||||
description = _L("migrate.success.descriptionSingle"),
|
||||
type = "success",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
end)
|
||||
|
||||
lib.addCommand("migrateskins", {
|
||||
help = "Migrate skins",
|
||||
params = {
|
||||
{
|
||||
name = "resourceName",
|
||||
type = "string",
|
||||
},
|
||||
},
|
||||
restricted = "group.god"
|
||||
}, function(source, args)
|
||||
local resourceName = args.resourceName
|
||||
if resourceName == "fivem-appearance" then
|
||||
MigrateFivemAppearance(source)
|
||||
elseif resourceName == "qb-clothing" then
|
||||
CreateThread(function()
|
||||
MigrateQBClothing(source)
|
||||
end)
|
||||
else
|
||||
lib.notify(source, {
|
||||
title = _L("migrate.typeError.title"),
|
||||
description = _L("migrate.typeError.description"),
|
||||
type = "error",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
end
|
||||
end)
|
44
resources/[il]/illenium-appearance/server/permissions.lua
Normal file
@ -0,0 +1,44 @@
|
||||
local resetTimer = GetGameTimer()
|
||||
local allAces = {}
|
||||
|
||||
lib.callback.register("illenium-appearance:server:GetPlayerAces", function()
|
||||
local src = source
|
||||
local allowedAces = {}
|
||||
for k in pairs(allAces) do
|
||||
if IsPlayerAceAllowed(src, k) then
|
||||
allowedAces[#allowedAces + 1] = k
|
||||
end
|
||||
end
|
||||
return allowedAces
|
||||
end)
|
||||
|
||||
local function findAceFromSecurityMessage(message)
|
||||
local words = {}
|
||||
for word in message:gmatch("%S+") do words[#words + 1] = word end
|
||||
return words[3]
|
||||
end
|
||||
|
||||
RegisterConsoleListener(function(channel, message)
|
||||
if channel ~= "security" then
|
||||
return
|
||||
end
|
||||
|
||||
local ace = findAceFromSecurityMessage(message)
|
||||
if ace and ((GetGameTimer() - resetTimer) > Config.ACEResetCooldown) then
|
||||
allAces = {}
|
||||
end
|
||||
|
||||
if ace then
|
||||
allAces[ace] = true
|
||||
resetTimer = GetGameTimer()
|
||||
end
|
||||
end)
|
||||
|
||||
if Config.EnableACEPermissions then
|
||||
CreateThread(function()
|
||||
while true do
|
||||
ExecuteCommand("list_aces")
|
||||
Wait(Config.ACEListCooldown)
|
||||
end
|
||||
end)
|
||||
end
|
365
resources/[il]/illenium-appearance/server/server.lua
Normal file
@ -0,0 +1,365 @@
|
||||
local outfitCache = {}
|
||||
local uniformCache = {}
|
||||
|
||||
local function getMoneyForShop(shopType)
|
||||
local money = 0
|
||||
if shopType == "clothing" then
|
||||
money = Config.ClothingCost
|
||||
elseif shopType == "barber" then
|
||||
money = Config.BarberCost
|
||||
elseif shopType == "tattoo" then
|
||||
money = Config.TattooCost
|
||||
elseif shopType == "surgeon" then
|
||||
money = Config.SurgeonCost
|
||||
end
|
||||
|
||||
return money
|
||||
end
|
||||
|
||||
local function getOutfitsForPlayer(citizenid)
|
||||
outfitCache[citizenid] = {}
|
||||
local result = Database.PlayerOutfits.GetAllByCitizenID(citizenid)
|
||||
for i = 1, #result, 1 do
|
||||
outfitCache[citizenid][#outfitCache[citizenid] + 1] = {
|
||||
id = result[i].id,
|
||||
name = result[i].outfitname,
|
||||
model = result[i].model,
|
||||
components = json.decode(result[i].components),
|
||||
props = json.decode(result[i].props)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
local function GenerateUniqueCode()
|
||||
local code, exists
|
||||
repeat
|
||||
code = GenerateNanoID(Config.OutfitCodeLength)
|
||||
exists = Database.PlayerOutfitCodes.GetByCode(code)
|
||||
until not exists
|
||||
return code
|
||||
end
|
||||
|
||||
-- Callback(s)
|
||||
|
||||
lib.callback.register("illenium-appearance:server:generateOutfitCode", function(_, outfitID)
|
||||
local existingOutfitCode = Database.PlayerOutfitCodes.GetByOutfitID(outfitID)
|
||||
if not existingOutfitCode then
|
||||
local code = GenerateUniqueCode()
|
||||
local id = Database.PlayerOutfitCodes.Add(outfitID, code)
|
||||
if not id then
|
||||
print("Something went wrong while generating outfit code")
|
||||
return
|
||||
end
|
||||
return code
|
||||
end
|
||||
return existingOutfitCode.code
|
||||
end)
|
||||
|
||||
lib.callback.register("illenium-appearance:server:importOutfitCode", function(source, outfitName, outfitCode)
|
||||
local citizenID = Framework.GetPlayerID(source)
|
||||
local existingOutfitCode = Database.PlayerOutfitCodes.GetByCode(outfitCode)
|
||||
if not existingOutfitCode then
|
||||
return nil
|
||||
end
|
||||
|
||||
local playerOutfit = Database.PlayerOutfits.GetByID(existingOutfitCode.outfitid)
|
||||
if not playerOutfit then
|
||||
return
|
||||
end
|
||||
|
||||
if playerOutfit.citizenid == citizenID then return end -- Validation when someone tried to duplicate own outfit
|
||||
if Database.PlayerOutfits.GetByOutfit(outfitName, citizenID) then return end -- Validation duplicate outfit name, if validate on local id, someone can "spam error" server-sided
|
||||
|
||||
local id = Database.PlayerOutfits.Add(citizenID, outfitName, playerOutfit.model, playerOutfit.components, playerOutfit.props)
|
||||
|
||||
if not id then
|
||||
print("Something went wrong while importing the outfit")
|
||||
return
|
||||
end
|
||||
|
||||
outfitCache[citizenID][#outfitCache[citizenID] + 1] = {
|
||||
id = id,
|
||||
name = outfitName,
|
||||
model = playerOutfit.model,
|
||||
components = json.decode(playerOutfit.components),
|
||||
props = json.decode(playerOutfit.props)
|
||||
}
|
||||
|
||||
return true
|
||||
end)
|
||||
|
||||
lib.callback.register("illenium-appearance:server:getAppearance", function(source, model)
|
||||
local citizenID = Framework.GetPlayerID(source)
|
||||
return Framework.GetAppearance(citizenID, model)
|
||||
end)
|
||||
|
||||
lib.callback.register("illenium-appearance:server:hasMoney", function(source, shopType)
|
||||
local money = getMoneyForShop(shopType)
|
||||
if Framework.HasMoney(source, "cash", money) or Framework.HasMoney(source, "bank", money) then
|
||||
return true, money
|
||||
else
|
||||
return false, money
|
||||
end
|
||||
end)
|
||||
|
||||
lib.callback.register("illenium-appearance:server:payForTattoo", function(source, tattoo)
|
||||
local src = source
|
||||
local cost = tattoo.cost or Config.TattooCost
|
||||
|
||||
if Framework.RemoveMoney(src, "cash", cost) or Framework.RemoveMoney(src, "bank", cost) then
|
||||
lib.notify(src, {
|
||||
title = _L("purchase.tattoo.success.title"),
|
||||
description = string.format(_L("purchase.tattoo.success.description"), tattoo.label, cost),
|
||||
type = "success",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
return true
|
||||
else
|
||||
lib.notify(src, {
|
||||
title = _L("purchase.tattoo.failure.title"),
|
||||
description = _L("purchase.tattoo.failure.description"),
|
||||
type = "error",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
return false
|
||||
end
|
||||
end)
|
||||
|
||||
lib.callback.register("illenium-appearance:server:getOutfits", function(source)
|
||||
local citizenID = Framework.GetPlayerID(source)
|
||||
if outfitCache[citizenID] == nil then
|
||||
getOutfitsForPlayer(citizenID)
|
||||
end
|
||||
return outfitCache[citizenID]
|
||||
end)
|
||||
|
||||
lib.callback.register("illenium-appearance:server:getManagementOutfits", function(source, mType, gender)
|
||||
local job = Framework.GetJob(source)
|
||||
if mType == "Gang" then
|
||||
job = Framework.GetGang(source)
|
||||
end
|
||||
|
||||
local grade = tonumber(job.grade.level)
|
||||
local managementOutfits = {}
|
||||
local result = Database.ManagementOutfits.GetAllByJob(mType, job.name, gender)
|
||||
|
||||
for i = 1, #result, 1 do
|
||||
if grade >= result[i].minrank then
|
||||
managementOutfits[#managementOutfits + 1] = {
|
||||
id = result[i].id,
|
||||
name = result[i].name,
|
||||
model = result[i].model,
|
||||
gender = result[i].gender,
|
||||
components = json.decode(result[i].components),
|
||||
props = json.decode(result[i].props)
|
||||
}
|
||||
end
|
||||
end
|
||||
return managementOutfits
|
||||
end)
|
||||
|
||||
lib.callback.register("illenium-appearance:server:getUniform", function(source)
|
||||
return uniformCache[Framework.GetPlayerID(source)]
|
||||
end)
|
||||
|
||||
RegisterServerEvent("illenium-appearance:server:saveAppearance", function(appearance)
|
||||
local src = source
|
||||
local citizenID = Framework.GetPlayerID(src)
|
||||
if appearance ~= nil then
|
||||
Framework.SaveAppearance(appearance, citizenID)
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterServerEvent("illenium-appearance:server:chargeCustomer", function(shopType)
|
||||
local label
|
||||
local src = source
|
||||
local money = getMoneyForShop(shopType)
|
||||
if Framework.RemoveMoney(src, "cash", money) or Framework.RemoveMoney(src, "bank", money) then
|
||||
if shopType == "clothing" then
|
||||
label = "tøj"
|
||||
elseif shopType == "barber" then
|
||||
label = "hårklipning"
|
||||
elseif shopType == "tattoo" then
|
||||
label = "tatovering"
|
||||
elseif shopType == "surgeon" then
|
||||
label = "kirurgi"
|
||||
end
|
||||
|
||||
lib.notify(src, {
|
||||
title = _L("purchase.store.success.title"),
|
||||
description = string.format(_L("purchase.store.success.description"), label, money),
|
||||
type = "success",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
else
|
||||
lib.notify(src, {
|
||||
title = _L("purchase.store.failure.title"),
|
||||
description = _L("purchase.store.failure.description"),
|
||||
type = "error",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:server:saveOutfit", function(name, model, components, props)
|
||||
local src = source
|
||||
local citizenID = Framework.GetPlayerID(src)
|
||||
if outfitCache[citizenID] == nil then
|
||||
getOutfitsForPlayer(citizenID)
|
||||
end
|
||||
if model and components and props then
|
||||
local id = Database.PlayerOutfits.Add(citizenID, name, model, json.encode(components), json.encode(props))
|
||||
if not id then
|
||||
return
|
||||
end
|
||||
outfitCache[citizenID][#outfitCache[citizenID] + 1] = {
|
||||
id = id,
|
||||
name = name,
|
||||
model = model,
|
||||
components = components,
|
||||
props = props
|
||||
}
|
||||
lib.notify(src, {
|
||||
title = _L("outfits.save.success.title"),
|
||||
description = string.format(_L("outfits.save.success.description"), name),
|
||||
type = "success",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:server:updateOutfit", function(id, model, components, props)
|
||||
local src = source
|
||||
local citizenID = Framework.GetPlayerID(src)
|
||||
if outfitCache[citizenID] == nil then
|
||||
getOutfitsForPlayer(citizenID)
|
||||
end
|
||||
if model and components and props then
|
||||
if not Database.PlayerOutfits.Update(id, model, json.encode(components), json.encode(props)) then return end
|
||||
local outfitName = ""
|
||||
for i = 1, #outfitCache[citizenID], 1 do
|
||||
local outfit = outfitCache[citizenID][i]
|
||||
if outfit.id == id then
|
||||
outfit.model = model
|
||||
outfit.components = components
|
||||
outfit.props = props
|
||||
outfitName = outfit.name
|
||||
break
|
||||
end
|
||||
end
|
||||
lib.notify(src, {
|
||||
title = _L("outfits.update.success.title"),
|
||||
description = string.format(_L("outfits.update.success.description"), outfitName),
|
||||
type = "success",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:server:saveManagementOutfit", function(outfitData)
|
||||
local src = source
|
||||
local id = Database.ManagementOutfits.Add(outfitData)
|
||||
if not id then
|
||||
return
|
||||
end
|
||||
|
||||
lib.notify(src, {
|
||||
title = _L("outfits.save.success.title"),
|
||||
description = string.format(_L("outfits.save.success.description"), outfitData.Name),
|
||||
type = "success",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
end)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:server:deleteManagementOutfit", function(id)
|
||||
Database.ManagementOutfits.DeleteByID(id)
|
||||
end)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:server:syncUniform", function(uniform)
|
||||
local src = source
|
||||
uniformCache[Framework.GetPlayerID(src)] = uniform
|
||||
end)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:server:deleteOutfit", function(id)
|
||||
local src = source
|
||||
local citizenID = Framework.GetPlayerID(src)
|
||||
Database.PlayerOutfitCodes.DeleteByOutfitID(id)
|
||||
Database.PlayerOutfits.DeleteByID(id)
|
||||
|
||||
for k, v in ipairs(outfitCache[citizenID]) do
|
||||
if v.id == id then
|
||||
table.remove(outfitCache[citizenID], k)
|
||||
break
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:server:resetOutfitCache", function()
|
||||
local src = source
|
||||
local citizenID = Framework.GetPlayerID(src)
|
||||
if citizenID then
|
||||
outfitCache[citizenID] = nil
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:server:ChangeRoutingBucket", function()
|
||||
local src = source
|
||||
SetPlayerRoutingBucket(src, src)
|
||||
end)
|
||||
|
||||
RegisterNetEvent("illenium-appearance:server:ResetRoutingBucket", function()
|
||||
local src = source
|
||||
SetPlayerRoutingBucket(src, 0)
|
||||
end)
|
||||
|
||||
if Config.EnablePedMenu then
|
||||
lib.addCommand("pedmenu", {
|
||||
help = _L("commands.pedmenu.title"),
|
||||
params = {
|
||||
{
|
||||
name = "playerID",
|
||||
type = "number",
|
||||
help = "Target player's server id",
|
||||
optional = true
|
||||
},
|
||||
},
|
||||
restricted = Config.PedMenuGroup
|
||||
}, function(source, args)
|
||||
local target = source
|
||||
if args.playerID then
|
||||
local citizenID = Framework.GetPlayerID(args.playerID)
|
||||
if citizenID then
|
||||
target = args.playerID
|
||||
else
|
||||
lib.notify(source, {
|
||||
title = _L("commands.pedmenu.failure.title"),
|
||||
description = _L("commands.pedmenu.failure.description"),
|
||||
type = "error",
|
||||
position = Config.NotifyOptions.position
|
||||
})
|
||||
return
|
||||
end
|
||||
end
|
||||
TriggerClientEvent("illenium-appearance:client:openClothingShopMenu", target, true)
|
||||
end)
|
||||
end
|
||||
|
||||
if Config.EnableJobOutfitsCommand then
|
||||
lib.addCommand("joboutfits", { help = _L("commands.joboutfits.title"), }, function(source)
|
||||
TriggerClientEvent("illenium-apearance:client:outfitsCommand", source, true)
|
||||
end)
|
||||
|
||||
lib.addCommand("gangoutfits", { help = _L("commands.gangoutfits.title"), }, function(source)
|
||||
TriggerClientEvent("illenium-apearance:client:outfitsCommand", source)
|
||||
end)
|
||||
end
|
||||
|
||||
lib.addCommand("reloadskin", { help = _L("commands.reloadskin.title") }, function(source)
|
||||
TriggerClientEvent("illenium-appearance:client:reloadSkin", source)
|
||||
end)
|
||||
|
||||
lib.addCommand("clearstuckprops", { help = _L("commands.clearstuckprops.title") }, function(source)
|
||||
TriggerClientEvent("illenium-appearance:client:ClearStuckProps", source)
|
||||
end)
|
||||
|
||||
lib.versionCheck("iLLeniumStudios/illenium-appearance")
|
12
resources/[il]/illenium-appearance/server/util.lua
Normal file
@ -0,0 +1,12 @@
|
||||
math.randomseed(os.time())
|
||||
|
||||
local urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"
|
||||
|
||||
function GenerateNanoID(size)
|
||||
local id = ""
|
||||
for _ = 1, size do
|
||||
local randomIndex = math.random(64)
|
||||
id = id .. urlAlphabet:sub(randomIndex,randomIndex)
|
||||
end
|
||||
return id
|
||||
end
|
46
resources/[il]/illenium-appearance/shared/blacklist.lua
Normal file
@ -0,0 +1,46 @@
|
||||
Config.Blacklist = {
|
||||
male = {
|
||||
hair = {},
|
||||
components = {
|
||||
masks = {},
|
||||
upperBody = {},
|
||||
lowerBody = {},
|
||||
bags = {},
|
||||
shoes = {},
|
||||
scarfAndChains = {},
|
||||
shirts = {},
|
||||
bodyArmor = {},
|
||||
decals = {},
|
||||
jackets = {}
|
||||
},
|
||||
props = {
|
||||
hats = {},
|
||||
glasses = {},
|
||||
ear = {},
|
||||
watches = {},
|
||||
bracelets = {}
|
||||
}
|
||||
},
|
||||
female = {
|
||||
hair = {},
|
||||
components = {
|
||||
masks = {},
|
||||
upperBody = {},
|
||||
lowerBody = {},
|
||||
bags = {},
|
||||
shoes = {},
|
||||
scarfAndChains = {},
|
||||
shirts = {},
|
||||
bodyArmor = {},
|
||||
decals = {},
|
||||
jackets = {}
|
||||
},
|
||||
props = {
|
||||
hats = {},
|
||||
glasses = {},
|
||||
ear = {},
|
||||
watches = {},
|
||||
bracelets = {}
|
||||
}
|
||||
}
|
||||
}
|
1360
resources/[il]/illenium-appearance/shared/config.lua
Normal file
@ -0,0 +1,96 @@
|
||||
if not Framework.ESX() then return end
|
||||
|
||||
function Framework.ConvertComponents(oldSkin, components)
|
||||
return {
|
||||
{
|
||||
component_id = 0,
|
||||
drawable = (components and components[1].drawable) or 0,
|
||||
texture = (components and components[1].texture) or 0
|
||||
},
|
||||
{
|
||||
component_id = 1,
|
||||
drawable = oldSkin.mask_1 or (components and components[2].drawable) or 0,
|
||||
texture = oldSkin.mask_2 or (components and components[2].texture) or 0
|
||||
},
|
||||
{
|
||||
component_id = 2,
|
||||
drawable = (components and components[3].drawable) or 0,
|
||||
texture = (components and components[3].texture) or 0
|
||||
},
|
||||
{
|
||||
component_id = 3,
|
||||
drawable = oldSkin.arms or (components and components[4].drawable) or 0,
|
||||
texture = oldSkin.arms_2 or (components and components[4].texture) or 0,
|
||||
},
|
||||
{
|
||||
component_id = 4,
|
||||
drawable = oldSkin.pants_1 or (components and components[5].drawable) or 0,
|
||||
texture = oldSkin.pants_2 or (components and components[5].texture) or 0
|
||||
},
|
||||
{
|
||||
component_id = 5,
|
||||
drawable = oldSkin.bags_1 or (components and components[6].drawable) or 0,
|
||||
texture = oldSkin.bags_2 or (components and components[6].texture) or 0
|
||||
},
|
||||
{
|
||||
component_id = 6,
|
||||
drawable = oldSkin.shoes_1 or (components and components[7].drawable) or 0,
|
||||
texture = oldSkin.shoes_2 or (components and components[7].texture) or 0
|
||||
},
|
||||
{
|
||||
component_id = 7,
|
||||
drawable = oldSkin.chain_1 or (components and components[8].drawable) or 0,
|
||||
texture = oldSkin.chain_2 or (components and components[8].texture) or 0
|
||||
},
|
||||
{
|
||||
component_id = 8,
|
||||
drawable = oldSkin.tshirt_1 or (components and components[9].drawable) or 0,
|
||||
texture = oldSkin.tshirt_2 or (components and components[9].texture) or 0
|
||||
},
|
||||
{
|
||||
component_id = 9,
|
||||
drawable = oldSkin.bproof_1 or (components and components[10].drawable) or 0,
|
||||
texture = oldSkin.bproof_2 or (components and components[10].texture) or 0
|
||||
},
|
||||
{
|
||||
component_id = 10,
|
||||
drawable = oldSkin.decals_1 or (components and components[11].drawable) or 0,
|
||||
texture = oldSkin.decals_2 or (components and components[11].texture) or 0
|
||||
},
|
||||
{
|
||||
component_id = 11,
|
||||
drawable = oldSkin.torso_1 or (components and components[12].drawable) or 0,
|
||||
texture = oldSkin.torso_2 or (components and components[12].texture) or 0
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
function Framework.ConvertProps(oldSkin, props)
|
||||
return {
|
||||
{
|
||||
texture = oldSkin.helmet_2 or (props and props[1].texture) or -1,
|
||||
drawable = oldSkin.helmet_1 or (props and props[1].drawable) or -1,
|
||||
prop_id = 0
|
||||
},
|
||||
{
|
||||
texture = oldSkin.glasses_2 or (props and props[2].texture) or -1,
|
||||
drawable = oldSkin.glasses_1 or (props and props[2].drawable) or -1,
|
||||
prop_id = 1
|
||||
},
|
||||
{
|
||||
texture = oldSkin.ears_2 or (props and props[3].texture) or -1,
|
||||
drawable = oldSkin.ears_1 or (props and props[3].drawable) or -1,
|
||||
prop_id = 2
|
||||
},
|
||||
{
|
||||
texture = oldSkin.watches_2 or (props and props[4].texture) or -1,
|
||||
drawable = oldSkin.watches_1 or (props and props[4].drawable) or -1,
|
||||
prop_id = 6
|
||||
},
|
||||
{
|
||||
texture = oldSkin.bracelets_2 or (props and props[5].texture) or -1,
|
||||
drawable = oldSkin.bracelets_1 or (props and props[5].drawable) or -1,
|
||||
prop_id = 7
|
||||
}
|
||||
}
|
||||
end
|
@ -0,0 +1,9 @@
|
||||
Framework = {}
|
||||
|
||||
function Framework.ESX()
|
||||
return GetResourceState("es_extended") ~= "missing"
|
||||
end
|
||||
|
||||
function Framework.QBCore()
|
||||
return GetResourceState("qb-core") ~= "missing"
|
||||
end
|
839
resources/[il]/illenium-appearance/shared/peds.lua
Normal file
@ -0,0 +1,839 @@
|
||||
Config.Peds = {
|
||||
pedConfig = {
|
||||
{
|
||||
peds = {
|
||||
"mp_m_freemode_01",
|
||||
"mp_f_freemode_01",
|
||||
"a_f_m_beach_01",
|
||||
"a_f_m_bevhills_01",
|
||||
"a_f_m_bevhills_02",
|
||||
"a_f_m_bodybuild_01",
|
||||
"a_f_m_business_02",
|
||||
"a_f_m_downtown_01",
|
||||
"a_f_m_eastsa_01",
|
||||
"a_f_m_eastsa_02",
|
||||
"a_f_m_fatbla_01",
|
||||
"a_f_m_fatcult_01",
|
||||
"a_f_m_fatwhite_01",
|
||||
"a_f_m_ktown_01",
|
||||
"a_f_m_ktown_02",
|
||||
"a_f_m_prolhost_01",
|
||||
"a_f_m_salton_01",
|
||||
"a_f_m_skidrow_01",
|
||||
"a_f_m_soucent_01",
|
||||
"a_f_m_soucent_02",
|
||||
"a_f_m_soucentmc_01",
|
||||
"a_f_m_tourist_01",
|
||||
"a_f_m_tramp_01",
|
||||
"a_f_m_trampbeac_01",
|
||||
"a_f_o_genstreet_01",
|
||||
"a_f_o_indian_01",
|
||||
"a_f_o_ktown_01",
|
||||
"a_f_o_salton_01",
|
||||
"a_f_o_soucent_01",
|
||||
"a_f_o_soucent_02",
|
||||
"a_f_y_beach_01",
|
||||
"a_f_y_bevhills_01",
|
||||
"a_f_y_bevhills_02",
|
||||
"a_f_y_bevhills_03",
|
||||
"a_f_y_bevhills_04",
|
||||
"a_f_y_business_01",
|
||||
"a_f_y_business_02",
|
||||
"a_f_y_business_03",
|
||||
"a_f_y_business_04",
|
||||
"a_f_y_clubcust_01",
|
||||
"a_f_y_clubcust_02",
|
||||
"a_f_y_clubcust_03",
|
||||
"a_f_y_eastsa_01",
|
||||
"a_f_y_eastsa_02",
|
||||
"a_f_y_eastsa_03",
|
||||
"a_f_y_epsilon_01",
|
||||
"a_f_y_femaleagent",
|
||||
"a_f_y_fitness_01",
|
||||
"a_f_y_fitness_02",
|
||||
"a_f_y_genhot_01",
|
||||
"a_f_y_golfer_01",
|
||||
"a_f_y_hiker_01",
|
||||
"a_f_y_hippie_01",
|
||||
"a_f_y_hipster_01",
|
||||
"a_f_y_hipster_02",
|
||||
"a_f_y_hipster_03",
|
||||
"a_f_y_hipster_04",
|
||||
"a_f_y_indian_01",
|
||||
"a_f_y_juggalo_01",
|
||||
"a_f_y_runner_01",
|
||||
"a_f_y_rurmeth_01",
|
||||
"a_f_y_scdressy_01",
|
||||
"a_f_y_skater_01",
|
||||
"a_f_y_soucent_01",
|
||||
"a_f_y_soucent_02",
|
||||
"a_f_y_soucent_03",
|
||||
"a_f_y_tennis_01",
|
||||
"a_f_y_topless_01",
|
||||
"a_f_y_tourist_01",
|
||||
"a_f_y_tourist_02",
|
||||
"a_f_y_vinewood_01",
|
||||
"a_f_y_vinewood_02",
|
||||
"a_f_y_vinewood_03",
|
||||
"a_f_y_vinewood_04",
|
||||
"a_f_y_yoga_01",
|
||||
"a_f_y_gencaspat_01",
|
||||
"a_f_y_smartcaspat_01",
|
||||
"a_m_m_acult_01",
|
||||
"a_m_m_afriamer_01",
|
||||
"a_m_m_beach_01",
|
||||
"a_m_m_beach_02",
|
||||
"a_m_m_bevhills_01",
|
||||
"a_m_m_bevhills_02",
|
||||
"a_m_m_business_01",
|
||||
"a_m_m_eastsa_01",
|
||||
"a_m_m_eastsa_02",
|
||||
"a_m_m_farmer_01",
|
||||
"a_m_m_fatlatin_01",
|
||||
"a_m_m_genfat_01",
|
||||
"a_m_m_genfat_02",
|
||||
"a_m_m_golfer_01",
|
||||
"a_m_m_hasjew_01",
|
||||
"a_m_m_hillbilly_01",
|
||||
"a_m_m_hillbilly_02",
|
||||
"a_m_m_indian_01",
|
||||
"a_m_m_ktown_01",
|
||||
"a_m_m_malibu_01",
|
||||
"a_m_m_mexcntry_01",
|
||||
"a_m_m_mexlabor_01",
|
||||
"a_m_m_og_boss_01",
|
||||
"a_m_m_paparazzi_01",
|
||||
"a_m_m_polynesian_01",
|
||||
"a_m_m_prolhost_01",
|
||||
"a_m_m_rurmeth_01",
|
||||
"a_m_m_salton_01",
|
||||
"a_m_m_salton_02",
|
||||
"a_m_m_salton_03",
|
||||
"a_m_m_salton_04",
|
||||
"a_m_m_skater_01",
|
||||
"a_m_m_skidrow_01",
|
||||
"a_m_m_socenlat_01",
|
||||
"a_m_m_soucent_01",
|
||||
"a_m_m_soucent_02",
|
||||
"a_m_m_soucent_03",
|
||||
"a_m_m_soucent_04",
|
||||
"a_m_m_stlat_02",
|
||||
"a_m_m_tennis_01",
|
||||
"a_m_m_tourist_01",
|
||||
"a_m_m_tramp_01",
|
||||
"a_m_m_trampbeac_01",
|
||||
"a_m_m_tranvest_01",
|
||||
"a_m_m_tranvest_02",
|
||||
"a_m_o_acult_01",
|
||||
"a_m_o_acult_02",
|
||||
"a_m_o_beach_01",
|
||||
"a_m_o_genstreet_01",
|
||||
"a_m_o_ktown_01",
|
||||
"a_m_o_salton_01",
|
||||
"a_m_o_soucent_01",
|
||||
"a_m_o_soucent_02",
|
||||
"a_m_o_soucent_03",
|
||||
"a_m_o_tramp_01",
|
||||
"a_m_y_acult_01",
|
||||
"a_m_y_acult_02",
|
||||
"a_m_y_beach_01",
|
||||
"a_m_y_beach_02",
|
||||
"a_m_y_beach_03",
|
||||
"a_m_y_beachvesp_01",
|
||||
"a_m_y_beachvesp_02",
|
||||
"a_m_y_bevhills_01",
|
||||
"a_m_y_bevhills_02",
|
||||
"a_m_y_breakdance_01",
|
||||
"a_m_y_busicas_01",
|
||||
"a_m_y_business_01",
|
||||
"a_m_y_business_02",
|
||||
"a_m_y_business_03",
|
||||
"a_m_y_clubcust_01",
|
||||
"a_m_y_clubcust_02",
|
||||
"a_m_y_clubcust_03",
|
||||
"a_m_y_cyclist_01",
|
||||
"a_m_y_dhill_01",
|
||||
"a_m_y_downtown_01",
|
||||
"a_m_y_eastsa_01",
|
||||
"a_m_y_eastsa_02",
|
||||
"a_m_y_epsilon_01",
|
||||
"a_m_y_epsilon_02",
|
||||
"a_m_y_gay_01",
|
||||
"a_m_y_gay_02",
|
||||
"a_m_y_genstreet_01",
|
||||
"a_m_y_genstreet_02",
|
||||
"a_m_y_golfer_01",
|
||||
"a_m_y_hasjew_01",
|
||||
"a_m_y_hiker_01",
|
||||
"a_m_y_hippy_01",
|
||||
"a_m_y_hipster_01",
|
||||
"a_m_y_hipster_02",
|
||||
"a_m_y_hipster_03",
|
||||
"a_m_y_indian_01",
|
||||
"a_m_y_jetski_01",
|
||||
"a_m_y_juggalo_01",
|
||||
"a_m_y_ktown_01",
|
||||
"a_m_y_ktown_02",
|
||||
"a_m_y_latino_01",
|
||||
"a_m_y_methhead_01",
|
||||
"a_m_y_mexthug_01",
|
||||
"a_m_y_motox_01",
|
||||
"a_m_y_motox_02",
|
||||
"a_m_y_musclbeac_01",
|
||||
"a_m_y_musclbeac_02",
|
||||
"a_m_y_polynesian_01",
|
||||
"a_m_y_roadcyc_01",
|
||||
"a_m_y_runner_01",
|
||||
"a_m_y_runner_02",
|
||||
"a_m_y_salton_01",
|
||||
"a_m_y_skater_01",
|
||||
"a_m_y_skater_02",
|
||||
"a_m_y_soucent_01",
|
||||
"a_m_y_soucent_02",
|
||||
"a_m_y_soucent_03",
|
||||
"a_m_y_soucent_04",
|
||||
"a_m_y_stbla_01",
|
||||
"a_m_y_stbla_02",
|
||||
"a_m_y_stlat_01",
|
||||
"a_m_y_stwhi_01",
|
||||
"a_m_y_stwhi_02",
|
||||
"a_m_y_sunbathe_01",
|
||||
"a_m_y_surfer_01",
|
||||
"a_m_y_vindouche_01",
|
||||
"a_m_y_vinewood_01",
|
||||
"a_m_y_vinewood_02",
|
||||
"a_m_y_vinewood_03",
|
||||
"a_m_y_vinewood_04",
|
||||
"a_m_y_yoga_01",
|
||||
"a_m_m_mlcrisis_01",
|
||||
"a_m_y_gencaspat_01",
|
||||
"a_m_y_smartcaspat_01",
|
||||
"a_c_boar",
|
||||
"a_c_cat_01",
|
||||
"a_c_chickenhawk",
|
||||
"a_c_chimp",
|
||||
"a_c_chop",
|
||||
"a_c_cormorant",
|
||||
"a_c_cow",
|
||||
"a_c_coyote",
|
||||
"a_c_crow",
|
||||
"a_c_deer",
|
||||
"a_c_dolphin",
|
||||
"a_c_fish",
|
||||
"a_c_hen",
|
||||
"a_c_humpback",
|
||||
"a_c_husky",
|
||||
"a_c_killerwhale",
|
||||
"a_c_mtlion",
|
||||
"a_c_pig",
|
||||
"a_c_pigeon",
|
||||
"a_c_poodle",
|
||||
"a_c_pug",
|
||||
"a_c_rabbit_01",
|
||||
"a_c_rat",
|
||||
"a_c_retriever",
|
||||
"a_c_rhesus",
|
||||
"a_c_rottweiler",
|
||||
"a_c_seagull",
|
||||
"a_c_sharkhammer",
|
||||
"a_c_sharktiger",
|
||||
"a_c_shepherd",
|
||||
"a_c_stingray",
|
||||
"a_c_westy",
|
||||
"cs_amandatownley",
|
||||
"cs_andreas",
|
||||
"cs_ashley",
|
||||
"cs_bankman",
|
||||
"cs_barry",
|
||||
"cs_beverly",
|
||||
"cs_brad",
|
||||
"cs_bradcadaver",
|
||||
"cs_carbuyer",
|
||||
"cs_casey",
|
||||
"cs_chengsr",
|
||||
"cs_chrisformage",
|
||||
"cs_clay",
|
||||
"cs_dale",
|
||||
"cs_davenorton",
|
||||
"cs_debra",
|
||||
"cs_denise",
|
||||
"cs_devin",
|
||||
"cs_dom",
|
||||
"cs_dreyfuss",
|
||||
"cs_drfriedlander",
|
||||
"cs_fabien",
|
||||
"cs_fbisuit_01",
|
||||
"cs_floyd",
|
||||
"cs_guadalope",
|
||||
"cs_gurk",
|
||||
"cs_hunter",
|
||||
"cs_janet",
|
||||
"cs_jewelass",
|
||||
"cs_jimmyboston",
|
||||
"cs_jimmydisanto",
|
||||
"cs_joeminuteman",
|
||||
"cs_johnnyklebitz",
|
||||
"cs_josef",
|
||||
"cs_josh",
|
||||
"cs_karen_daniels",
|
||||
"cs_lamardavis",
|
||||
"cs_lazlow",
|
||||
"cs_lazlow_2",
|
||||
"cs_lestercrest",
|
||||
"cs_lifeinvad_01",
|
||||
"cs_magenta",
|
||||
"cs_manuel",
|
||||
"cs_marnie",
|
||||
"cs_martinmadrazo",
|
||||
"cs_maryann",
|
||||
"cs_michelle",
|
||||
"cs_milton",
|
||||
"cs_molly",
|
||||
"cs_movpremf_01",
|
||||
"cs_movpremmale",
|
||||
"cs_mrk",
|
||||
"cs_mrs_thornhill",
|
||||
"cs_mrsphillips",
|
||||
"cs_natalia",
|
||||
"cs_nervousron",
|
||||
"cs_nigel",
|
||||
"cs_old_man1a",
|
||||
"cs_old_man2",
|
||||
"cs_omega",
|
||||
"cs_orleans",
|
||||
"cs_paper",
|
||||
"cs_patricia",
|
||||
"cs_priest",
|
||||
"cs_prolsec_02",
|
||||
"cs_russiandrunk",
|
||||
"cs_siemonyetarian",
|
||||
"cs_solomon",
|
||||
"cs_stevehains",
|
||||
"cs_stretch",
|
||||
"cs_tanisha",
|
||||
"cs_taocheng",
|
||||
"cs_taostranslator",
|
||||
"cs_tenniscoach",
|
||||
"cs_terry",
|
||||
"cs_tom",
|
||||
"cs_tomepsilon",
|
||||
"cs_tracydisanto",
|
||||
"cs_wade",
|
||||
"cs_zimbor",
|
||||
"csb_abigail",
|
||||
"csb_agent",
|
||||
"csb_alan",
|
||||
"csb_anita",
|
||||
"csb_anton",
|
||||
"csb_avon",
|
||||
"csb_ballasog",
|
||||
"csb_bogdan",
|
||||
"csb_bride",
|
||||
"csb_bryony",
|
||||
"csb_burgerdrug",
|
||||
"csb_car3guy1",
|
||||
"csb_car3guy2",
|
||||
"csb_chef",
|
||||
"csb_chef2",
|
||||
"csb_chin_goon",
|
||||
"csb_cletus",
|
||||
"csb_cop",
|
||||
"csb_customer",
|
||||
"csb_denise_friend",
|
||||
"csb_dix",
|
||||
"csb_djblamadon",
|
||||
"csb_englishdave",
|
||||
"csb_fos_rep",
|
||||
"csb_g",
|
||||
"csb_groom",
|
||||
"csb_grove_str_dlr",
|
||||
"csb_hao",
|
||||
"csb_hugh",
|
||||
"csb_imran",
|
||||
"csb_jackhowitzer",
|
||||
"csb_janitor",
|
||||
"csb_maude",
|
||||
"csb_money",
|
||||
"csb_mp_agent14",
|
||||
"csb_mrs_r",
|
||||
"csb_mweather",
|
||||
"csb_ortega",
|
||||
"csb_oscar",
|
||||
"csb_paige",
|
||||
"csb_popov",
|
||||
"csb_porndudes",
|
||||
"csb_prologuedriver",
|
||||
"csb_prolsec",
|
||||
"csb_ramp_gang",
|
||||
"csb_ramp_hic",
|
||||
"csb_ramp_hipster",
|
||||
"csb_ramp_marine",
|
||||
"csb_ramp_mex",
|
||||
"csb_rashcosvki",
|
||||
"csb_reporter",
|
||||
"csb_roccopelosi",
|
||||
"csb_screen_writer",
|
||||
"csb_sol",
|
||||
"csb_stripper_01",
|
||||
"csb_stripper_02",
|
||||
"csb_talcc",
|
||||
"csb_talmm",
|
||||
"csb_tonya",
|
||||
"csb_tonyprince",
|
||||
"csb_trafficwarden",
|
||||
"csb_undercover",
|
||||
"csb_vagspeak",
|
||||
"csb_agatha",
|
||||
"csb_avery",
|
||||
"csb_brucie2",
|
||||
"csb_thornton",
|
||||
"csb_tomcasino",
|
||||
"csb_vincent",
|
||||
"g_f_importexport_01",
|
||||
"g_f_importexport_01",
|
||||
"g_f_y_ballas_01",
|
||||
"g_f_y_families_01",
|
||||
"g_f_y_lost_01",
|
||||
"g_f_y_vagos_01",
|
||||
"g_m_importexport_01",
|
||||
"g_m_m_armboss_01",
|
||||
"g_m_m_armgoon_01",
|
||||
"g_m_m_armlieut_01",
|
||||
"g_m_m_chemwork_01",
|
||||
"g_m_m_chiboss_01",
|
||||
"g_m_m_chicold_01",
|
||||
"g_m_m_chigoon_01",
|
||||
"g_m_m_chigoon_02",
|
||||
"g_m_m_korboss_01",
|
||||
"g_m_m_mexboss_01",
|
||||
"g_m_m_mexboss_02",
|
||||
"g_m_y_armgoon_02",
|
||||
"g_m_y_azteca_01",
|
||||
"g_m_y_ballaeast_01",
|
||||
"g_m_y_ballaorig_01",
|
||||
"g_m_y_ballasout_01",
|
||||
"g_m_y_famca_01",
|
||||
"g_m_y_famdnf_01",
|
||||
"g_m_y_famfor_01",
|
||||
"g_m_y_korean_01",
|
||||
"g_m_y_korean_02",
|
||||
"g_m_y_korlieut_01",
|
||||
"g_m_y_lost_01",
|
||||
"g_m_y_lost_02",
|
||||
"g_m_y_lost_03",
|
||||
"g_m_y_mexgang_01",
|
||||
"g_m_y_mexgoon_01",
|
||||
"g_m_y_mexgoon_02",
|
||||
"g_m_y_mexgoon_03",
|
||||
"g_m_y_pologoon_01",
|
||||
"g_m_y_pologoon_02",
|
||||
"g_m_y_salvaboss_01",
|
||||
"g_m_y_salvagoon_01",
|
||||
"g_m_y_salvagoon_02",
|
||||
"g_m_y_salvagoon_03",
|
||||
"g_m_y_strpunk_01",
|
||||
"g_m_y_strpunk_02",
|
||||
"g_m_m_casrn_01",
|
||||
"mp_f_bennymech_01",
|
||||
"mp_f_boatstaff_01",
|
||||
"mp_f_cardesign_01",
|
||||
"mp_f_chbar_01",
|
||||
"mp_f_cocaine_01",
|
||||
"mp_f_counterfeit_01",
|
||||
"mp_f_deadhooker",
|
||||
"mp_f_execpa_01",
|
||||
"mp_f_execpa_02",
|
||||
"mp_f_forgery_01",
|
||||
"mp_f_helistaff_01",
|
||||
"mp_f_meth_01",
|
||||
"mp_f_misty_01",
|
||||
"mp_f_stripperlite",
|
||||
"mp_f_weed_01",
|
||||
"mp_g_m_pros_01",
|
||||
"mp_m_avongoon",
|
||||
"mp_m_boatstaff_01",
|
||||
"mp_m_bogdangoon",
|
||||
"mp_m_claude_01",
|
||||
"mp_m_cocaine_01",
|
||||
"mp_m_counterfeit_01",
|
||||
"mp_m_exarmy_01",
|
||||
"mp_m_execpa_01",
|
||||
"mp_m_famdd_01",
|
||||
"mp_m_fibsec_01",
|
||||
"mp_m_forgery_01",
|
||||
"mp_m_g_vagfun_01",
|
||||
"mp_m_marston_01",
|
||||
"mp_m_meth_01",
|
||||
"mp_m_niko_01",
|
||||
"mp_m_securoguard_01",
|
||||
"mp_m_shopkeep_01",
|
||||
"mp_m_waremech_01",
|
||||
"mp_m_weapexp_01",
|
||||
"mp_m_weapwork_01",
|
||||
"mp_m_weed_01",
|
||||
"mp_s_m_armoured_01",
|
||||
"s_f_m_fembarber",
|
||||
"s_f_m_maid_01",
|
||||
"s_f_m_shop_high",
|
||||
"s_f_m_sweatshop_01",
|
||||
"s_f_y_airhostess_01",
|
||||
"s_f_y_bartender_01",
|
||||
"s_f_y_baywatch_01",
|
||||
"s_f_y_clubbar_01",
|
||||
"s_f_y_cop_01",
|
||||
"s_f_y_factory_01",
|
||||
"s_f_y_hooker_01",
|
||||
"s_f_y_hooker_02",
|
||||
"s_f_y_hooker_03",
|
||||
"s_f_y_migrant_01",
|
||||
"s_f_y_movprem_01",
|
||||
"s_f_y_ranger_01",
|
||||
"s_f_y_scrubs_01",
|
||||
"s_f_y_sheriff_01",
|
||||
"s_f_y_shop_low",
|
||||
"s_f_y_shop_mid",
|
||||
"s_f_y_stripper_01",
|
||||
"s_f_y_stripper_02",
|
||||
"s_f_y_stripperlite",
|
||||
"s_f_y_sweatshop_01",
|
||||
"s_f_y_casino_01",
|
||||
"s_m_m_ammucountry",
|
||||
"s_m_m_armoured_01",
|
||||
"s_m_m_armoured_02",
|
||||
"s_m_m_autoshop_01",
|
||||
"s_m_m_autoshop_02",
|
||||
"s_m_m_bouncer_01",
|
||||
"s_m_m_ccrew_01",
|
||||
"s_m_m_chemsec_01",
|
||||
"s_m_m_ciasec_01",
|
||||
"s_m_m_cntrybar_01",
|
||||
"s_m_m_dockwork_01",
|
||||
"s_m_m_doctor_01",
|
||||
"s_m_m_fiboffice_01",
|
||||
"s_m_m_fiboffice_02",
|
||||
"s_m_m_fibsec_01",
|
||||
"s_m_m_gaffer_01",
|
||||
"s_m_m_gardener_01",
|
||||
"s_m_m_gentransport",
|
||||
"s_m_m_hairdress_01",
|
||||
"s_m_m_highsec_01",
|
||||
"s_m_m_highsec_02",
|
||||
"s_m_m_janitor",
|
||||
"s_m_m_lathandy_01",
|
||||
"s_m_m_lifeinvad_01",
|
||||
"s_m_m_linecook",
|
||||
"s_m_m_lsmetro_01",
|
||||
"s_m_m_mariachi_01",
|
||||
"s_m_m_marine_01",
|
||||
"s_m_m_marine_02",
|
||||
"s_m_m_migrant_01",
|
||||
"s_m_m_movalien_01",
|
||||
"s_m_m_movprem_01",
|
||||
"s_m_m_movspace_01",
|
||||
"s_m_m_paramedic_01",
|
||||
"s_m_m_pilot_01",
|
||||
"s_m_m_pilot_02",
|
||||
"s_m_m_postal_01",
|
||||
"s_m_m_postal_02",
|
||||
"s_m_m_prisguard_01",
|
||||
"s_m_m_scientist_01",
|
||||
"s_m_m_security_01",
|
||||
"s_m_m_snowcop_01",
|
||||
"s_m_m_strperf_01",
|
||||
"s_m_m_strpreach_01",
|
||||
"s_m_m_strvend_01",
|
||||
"s_m_m_trucker_01",
|
||||
"s_m_m_ups_01",
|
||||
"s_m_m_ups_02",
|
||||
"s_m_o_busker_01",
|
||||
"s_m_y_airworker",
|
||||
"s_m_y_ammucity_01",
|
||||
"s_m_y_armymech_01",
|
||||
"s_m_y_autopsy_01",
|
||||
"s_m_y_barman_01",
|
||||
"s_m_y_baywatch_01",
|
||||
"s_m_y_blackops_01",
|
||||
"s_m_y_blackops_02",
|
||||
"s_m_y_blackops_03",
|
||||
"s_m_y_busboy_01",
|
||||
"s_m_y_chef_01",
|
||||
"s_m_y_clown_01",
|
||||
"s_m_y_clubbar_01",
|
||||
"s_m_y_construct_01",
|
||||
"s_m_y_construct_02",
|
||||
"s_m_y_cop_01",
|
||||
"s_m_y_dealer_01",
|
||||
"s_m_y_devinsec_01",
|
||||
"s_m_y_dockwork_01",
|
||||
"s_m_y_doorman_01",
|
||||
"s_m_y_dwservice_01",
|
||||
"s_m_y_dwservice_02",
|
||||
"s_m_y_factory_01",
|
||||
"s_m_y_fireman_01",
|
||||
"s_m_y_garbage",
|
||||
"s_m_y_grip_01",
|
||||
"s_m_y_hwaycop_01",
|
||||
"s_m_y_marine_01",
|
||||
"s_m_y_marine_02",
|
||||
"s_m_y_marine_03",
|
||||
"s_m_y_mime",
|
||||
"s_m_y_pestcont_01",
|
||||
"s_m_y_pilot_01",
|
||||
"s_m_y_prismuscl_01",
|
||||
"s_m_y_prisoner_01",
|
||||
"s_m_y_ranger_01",
|
||||
"s_m_y_robber_01",
|
||||
"s_m_y_sheriff_01",
|
||||
"s_m_y_shop_mask",
|
||||
"s_m_y_strvend_01",
|
||||
"s_m_y_swat_01",
|
||||
"s_m_y_uscg_01",
|
||||
"s_m_y_valet_01",
|
||||
"s_m_y_waiter_01",
|
||||
"s_m_y_waretech_01",
|
||||
"s_m_y_winclean_01",
|
||||
"s_m_y_xmech_01",
|
||||
"s_m_y_xmech_02",
|
||||
"s_m_y_casino_01",
|
||||
"s_m_y_westsec_01",
|
||||
"hc_driver",
|
||||
"hc_gunman",
|
||||
"hc_hacker",
|
||||
"ig_abigail",
|
||||
"ig_agent",
|
||||
"ig_amandatownley",
|
||||
"ig_andreas",
|
||||
"ig_ashley",
|
||||
"ig_avon",
|
||||
"ig_ballasog",
|
||||
"ig_bankman",
|
||||
"ig_barry",
|
||||
"ig_benny",
|
||||
"ig_bestmen",
|
||||
"ig_beverly",
|
||||
"ig_brad",
|
||||
"ig_bride",
|
||||
"ig_car3guy1",
|
||||
"ig_car3guy2",
|
||||
"ig_casey",
|
||||
"ig_chef",
|
||||
"ig_chef2",
|
||||
"ig_chengsr",
|
||||
"ig_chrisformage",
|
||||
"ig_clay",
|
||||
"ig_claypain",
|
||||
"ig_cletus",
|
||||
"ig_dale",
|
||||
"ig_davenorton",
|
||||
"ig_denise",
|
||||
"ig_devin",
|
||||
"ig_dix",
|
||||
"ig_djblamadon",
|
||||
"ig_djblamrupert",
|
||||
"ig_djblamryans",
|
||||
"ig_djdixmanager",
|
||||
"ig_djgeneric_01",
|
||||
"ig_djsolfotios",
|
||||
"ig_djsoljakob",
|
||||
"ig_djsolmanager",
|
||||
"ig_djsolmike",
|
||||
"ig_djsolrobt",
|
||||
"ig_djtalaurelia",
|
||||
"ig_djtalignazio",
|
||||
"ig_dom",
|
||||
"ig_dreyfuss",
|
||||
"ig_drfriedlander",
|
||||
"ig_englishdave",
|
||||
"ig_fabien",
|
||||
"ig_fbisuit_01",
|
||||
"ig_floyd",
|
||||
"ig_g",
|
||||
"ig_groom",
|
||||
"ig_hao",
|
||||
"ig_hunter",
|
||||
"ig_janet",
|
||||
"ig_jay_norris",
|
||||
"ig_jewelass",
|
||||
"ig_jimmyboston",
|
||||
"ig_jimmyboston_02",
|
||||
"ig_jimmydisanto",
|
||||
"ig_joeminuteman",
|
||||
"ig_johnnyklebitz",
|
||||
"ig_josef",
|
||||
"ig_josh",
|
||||
"ig_karen_daniels",
|
||||
"ig_kerrymcintosh",
|
||||
"ig_kerrymcintosh_02",
|
||||
"ig_lacey_jones_02",
|
||||
"ig_lamardavis",
|
||||
"ig_lazlow",
|
||||
"ig_lazlow_2",
|
||||
"ig_lestercrest",
|
||||
"ig_lestercrest_2",
|
||||
"ig_lifeinvad_01",
|
||||
"ig_lifeinvad_02",
|
||||
"ig_magenta",
|
||||
"ig_malc",
|
||||
"ig_manuel",
|
||||
"ig_marnie",
|
||||
"ig_maryann",
|
||||
"ig_maude",
|
||||
"ig_michelle",
|
||||
"ig_milton",
|
||||
"ig_molly",
|
||||
"ig_money",
|
||||
"ig_mp_agent14",
|
||||
"ig_mrk",
|
||||
"ig_mrs_thornhill",
|
||||
"ig_mrsphillips",
|
||||
"ig_natalia",
|
||||
"ig_nervousron",
|
||||
"ig_nigel",
|
||||
"ig_old_man1a",
|
||||
"ig_old_man2",
|
||||
"ig_omega",
|
||||
"ig_oneil",
|
||||
"ig_orleans",
|
||||
"ig_ortega",
|
||||
"ig_paige",
|
||||
"ig_paper",
|
||||
"ig_patricia",
|
||||
"ig_popov",
|
||||
"ig_priest",
|
||||
"ig_prolsec_02",
|
||||
"ig_ramp_gang",
|
||||
"ig_ramp_hic",
|
||||
"ig_ramp_hipster",
|
||||
"ig_ramp_mex",
|
||||
"ig_rashcosvki",
|
||||
"ig_roccopelosi",
|
||||
"ig_russiandrunk",
|
||||
"ig_sacha",
|
||||
"ig_screen_writer",
|
||||
"ig_siemonyetarian",
|
||||
"ig_sol",
|
||||
"ig_solomon",
|
||||
"ig_stevehains",
|
||||
"ig_stretch",
|
||||
"ig_talcc",
|
||||
"ig_talina",
|
||||
"ig_talmm",
|
||||
"ig_tanisha",
|
||||
"ig_taocheng",
|
||||
"ig_taostranslator",
|
||||
"ig_tenniscoach",
|
||||
"ig_terry",
|
||||
"ig_tomepsilon",
|
||||
"ig_tonya",
|
||||
"ig_tonyprince",
|
||||
"ig_tracydisanto",
|
||||
"ig_trafficwarden",
|
||||
"ig_tylerdix",
|
||||
"ig_tylerdix_02",
|
||||
"ig_vagspeak",
|
||||
"ig_wade",
|
||||
"ig_zimbor",
|
||||
"player_one",
|
||||
"player_two",
|
||||
"player_zero",
|
||||
"ig_agatha",
|
||||
"ig_avery",
|
||||
"ig_brucie2",
|
||||
"ig_thornton",
|
||||
"ig_tomcasino",
|
||||
"ig_vincent",
|
||||
"u_f_m_corpse_01",
|
||||
"u_f_m_miranda",
|
||||
"u_f_m_miranda_02",
|
||||
"u_f_m_promourn_01",
|
||||
"u_f_o_moviestar",
|
||||
"u_f_o_prolhost_01",
|
||||
"u_f_y_bikerchic",
|
||||
"u_f_y_comjane",
|
||||
"u_f_y_corpse_01",
|
||||
"u_f_y_corpse_02",
|
||||
"u_f_y_danceburl_01",
|
||||
"u_f_y_dancelthr_01",
|
||||
"u_f_y_dancerave_01",
|
||||
"u_f_y_hotposh_01",
|
||||
"u_f_y_jewelass_01",
|
||||
"u_f_y_mistress",
|
||||
"u_f_y_poppymich",
|
||||
"u_f_y_poppymich_02",
|
||||
"u_f_y_princess",
|
||||
"u_f_y_spyactress",
|
||||
"u_f_m_casinocash_01",
|
||||
"u_f_m_casinoshop_01",
|
||||
"u_f_m_debbie_01",
|
||||
"u_f_o_carol",
|
||||
"u_f_o_eileen",
|
||||
"u_f_y_beth",
|
||||
"u_f_y_lauren",
|
||||
"u_f_y_taylor",
|
||||
"u_m_m_aldinapoli",
|
||||
"u_m_m_bankman",
|
||||
"u_m_m_bikehire_01",
|
||||
"u_m_m_doa_01",
|
||||
"u_m_m_edtoh",
|
||||
"u_m_m_fibarchitect",
|
||||
"u_m_m_filmdirector",
|
||||
"u_m_m_glenstank_01",
|
||||
"u_m_m_griff_01",
|
||||
"u_m_m_jesus_01",
|
||||
"u_m_m_jewelsec_01",
|
||||
"u_m_m_jewelthief",
|
||||
"u_m_m_markfost",
|
||||
"u_m_m_partytarget",
|
||||
"u_m_m_prolsec_01",
|
||||
"u_m_m_promourn_01",
|
||||
"u_m_m_rivalpap",
|
||||
"u_m_m_spyactor",
|
||||
"u_m_m_streetart_01",
|
||||
"u_m_m_willyfist",
|
||||
"u_m_o_filmnoir",
|
||||
"u_m_o_finguru_01",
|
||||
"u_m_o_taphillbilly",
|
||||
"u_m_o_tramp_01",
|
||||
"u_m_y_abner",
|
||||
"u_m_y_antonb",
|
||||
"u_m_y_babyd",
|
||||
"u_m_y_baygor",
|
||||
"u_m_y_burgerdrug_01",
|
||||
"u_m_y_chip",
|
||||
"u_m_y_corpse_01",
|
||||
"u_m_y_cyclist_01",
|
||||
"u_m_y_danceburl_01",
|
||||
"u_m_y_dancelthr_01",
|
||||
"u_m_y_dancerave_01",
|
||||
"u_m_y_fibmugger_01",
|
||||
"u_m_y_guido_01",
|
||||
"u_m_y_gunvend_01",
|
||||
"u_m_y_hippie_01",
|
||||
"u_m_y_imporage",
|
||||
"u_m_y_juggernaut_01",
|
||||
"u_m_y_justin",
|
||||
"u_m_y_mani",
|
||||
"u_m_y_militarybum",
|
||||
"u_m_y_paparazzi",
|
||||
"u_m_y_party_01",
|
||||
"u_m_y_pogo_01",
|
||||
"u_m_y_prisoner_01",
|
||||
"u_m_y_proldriver_01",
|
||||
"u_m_y_rsranger_01",
|
||||
"u_m_y_sbike",
|
||||
"u_m_y_smugmech_01",
|
||||
"u_m_y_staggrm_01",
|
||||
"u_m_y_tattoo_01",
|
||||
"u_m_y_zombie_01",
|
||||
"u_m_m_blane",
|
||||
"u_m_m_curtis",
|
||||
"u_m_m_vince",
|
||||
"u_m_o_dean",
|
||||
"u_m_y_caleb",
|
||||
"u_m_y_croupthief_01",
|
||||
"u_m_y_gabriel",
|
||||
"u_m_y_ushi"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
6968
resources/[il]/illenium-appearance/shared/tattoos.lua
Normal file
61
resources/[il]/illenium-appearance/shared/theme.lua
Normal file
@ -0,0 +1,61 @@
|
||||
Config.Theme = {
|
||||
currentTheme = "qb-core",
|
||||
themes = {
|
||||
{
|
||||
id = "default",
|
||||
borderRadius = "4px",
|
||||
fontColor = "255, 255, 255",
|
||||
fontColorHover = "255, 255, 255",
|
||||
fontColorSelected = "0, 0, 0",
|
||||
fontFamily = "Inter",
|
||||
primaryBackground = "0, 0, 0",
|
||||
primaryBackgroundSelected = "255, 255, 255",
|
||||
secondaryBackground = "0, 0, 0",
|
||||
scaleOnHover = false,
|
||||
sectionFontWeight = "normal",
|
||||
smoothBackgroundTransition = false
|
||||
},
|
||||
{
|
||||
id = "qb-core",
|
||||
borderRadius = "3vh",
|
||||
fontColor = "255, 255, 255",
|
||||
fontColorHover = "255, 255, 255",
|
||||
fontColorSelected = "255, 255, 255",
|
||||
fontFamily = "Poppins",
|
||||
primaryBackground = "220, 20, 60",
|
||||
primaryBackgroundSelected = "220, 20, 60",
|
||||
secondaryBackground = "23, 23, 23",
|
||||
scaleOnHover = true,
|
||||
sectionFontWeight = "bold",
|
||||
smoothBackgroundTransition = true
|
||||
},
|
||||
{
|
||||
id = "project-sloth",
|
||||
borderRadius = "6vh",
|
||||
fontColor = "255, 255, 255",
|
||||
fontColorHover = "255, 255, 255",
|
||||
fontColorSelected = "255, 255, 255",
|
||||
fontFamily = "Inter",
|
||||
primaryBackground = "2, 241, 181",
|
||||
primaryBackgroundSelected = "2, 241, 181",
|
||||
secondaryBackground = "27, 24, 69",
|
||||
scaleOnHover = true,
|
||||
sectionFontWeight = "bold",
|
||||
smoothBackgroundTransition = false
|
||||
},
|
||||
{
|
||||
id = "not-heavily-inspired",
|
||||
borderRadius = "10vh",
|
||||
fontColor = "255, 255, 255",
|
||||
fontColorHover = "255, 255, 255",
|
||||
fontColorSelected = "255, 255, 255",
|
||||
fontFamily = "Inter",
|
||||
primaryBackground = "149, 239, 119",
|
||||
primaryBackgroundSelected = "242, 163, 101",
|
||||
secondaryBackground = "25, 46, 70",
|
||||
scaleOnHover = true,
|
||||
sectionFontWeight = "bold",
|
||||
smoothBackgroundTransition = false
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
CREATE TABLE IF NOT EXISTS `management_outfits` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`job_name` varchar(50) NOT NULL,
|
||||
`type` varchar(50) NOT NULL,
|
||||
`minrank` int(11) NOT NULL DEFAULT 0,
|
||||
`name` varchar(50) NOT NULL DEFAULT 'Cool Outfit',
|
||||
`gender` varchar(50) NOT NULL DEFAULT 'male',
|
||||
`model` varchar(50) DEFAULT NULL,
|
||||
`props` varchar(1000) DEFAULT NULL,
|
||||
`components` varchar(1500) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8mb4;
|
@ -0,0 +1,22 @@
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET NAMES utf8 */;
|
||||
/*!50503 SET NAMES utf8mb4 */;
|
||||
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
|
||||
/*!40103 SET TIME_ZONE='+00:00' */;
|
||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `player_outfit_codes` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`outfitid` int(11) NOT NULL,
|
||||
`code` varchar(50) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `FK_player_outfit_codes_player_outfits` (`outfitid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
/*!40103 SET TIME_ZONE=IFNULL(@OLD_TIME_ZONE, 'system') */;
|
||||
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=IFNULL(@OLD_FOREIGN_KEY_CHECKS, 1) */;
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40111 SET SQL_NOTES=IFNULL(@OLD_SQL_NOTES, 1) */;
|
24
resources/[il]/illenium-appearance/sql/player_outfits.sql
Normal file
@ -0,0 +1,24 @@
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET NAMES utf8 */;
|
||||
/*!50503 SET NAMES utf8mb4 */;
|
||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `player_outfits` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`citizenid` varchar(50) DEFAULT NULL,
|
||||
`outfitname` varchar(50) NOT NULL DEFAULT '0',
|
||||
`model` varchar(50) DEFAULT NULL,
|
||||
`props` varchar(1000) DEFAULT NULL,
|
||||
`components` varchar(1500) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `citizenid_outfitname_model` (`citizenid`,`outfitname`,`model`),
|
||||
KEY `citizenid` (`citizenid`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
|
||||
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=IFNULL(@OLD_FOREIGN_KEY_CHECKS, 1) */;
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40111 SET SQL_NOTES=IFNULL(@OLD_SQL_NOTES, 1) */;
|
10
resources/[il]/illenium-appearance/sql/playerskins.sql
Normal file
@ -0,0 +1,10 @@
|
||||
CREATE TABLE IF NOT EXISTS `playerskins` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`citizenid` varchar(255) NOT NULL,
|
||||
`model` varchar(255) NOT NULL,
|
||||
`skin` text NOT NULL,
|
||||
`active` tinyint(4) NOT NULL DEFAULT 1,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `citizenid` (`citizenid`),
|
||||
KEY `active` (`active`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
|
599
resources/[il]/illenium-appearance/web/dist/assets/index.b8e72b46.js
vendored
Normal file
17
resources/[il]/illenium-appearance/web/dist/index.html
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>UI</title>
|
||||
<script type="module" crossorigin src="./assets/index.b8e72b46.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
174
resources/[jims]/jim-beanmachine/client/chairs.lua
Normal file
@ -0,0 +1,174 @@
|
||||
local QBCore = exports[Config.Core]:GetCoreObject()
|
||||
|
||||
local beanseat = nil
|
||||
local sitting = false
|
||||
local Chairs = {}
|
||||
|
||||
CreateThread(function()
|
||||
for k, v in pairs(Config.Chairs) do
|
||||
Chairs["beanmachine"..k] =
|
||||
exports['qb-target']:AddBoxZone("beanmachine"..k, vec3(v.coords.x, v.coords.y, v.coords.z-1), 0.7, 0.7, { name="beanmachine"..k, heading = v.coords.w, debugPoly=Config.Debug, minZ = v.coords.z-1.2, maxZ = v.coords.z+0.1, },
|
||||
{ options = { { event = "jim-beanmachine:Chair", icon = "fas fa-chair", label = Loc[Config.Lan].targetinfo["sit_down"], loc = v.coords, stand = v.stand }, },
|
||||
distance = 2.2 })
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent('jim-beanmachine:Chair', function(data)
|
||||
local canSit = true
|
||||
local sitting = false
|
||||
local ped = PlayerPedId()
|
||||
for _, v in pairs(QBCore.Functions.GetPlayersFromCoords(data.loc.xyz, 0.6)) do
|
||||
local dist = #(GetEntityCoords(GetPlayerPed(v)) - data.loc.xyz)
|
||||
if dist <= 0.4 then triggerNotify(nil, Loc[Config.Lan].error["someone_already_sitting"]) canSit = false end
|
||||
end
|
||||
if canSit then
|
||||
if not IsPedHeadingTowardsPosition(ped, data.loc.xyz, 20.0) then TaskTurnPedToFaceCoord(ped, data.loc.xyz, 1500) Wait(1500) end
|
||||
if #(data.loc.xyz - GetEntityCoords(PlayerPedId())) > 1.5 then TaskGoStraightToCoord(ped, data.loc.xyz, 0.5, 1000, 0.0, 0) Wait(1100) end
|
||||
TaskStartScenarioAtPosition(PlayerPedId(), "PROP_HUMAN_SEAT_CHAIR_MP_PLAYER", data.loc.x, data.loc.y, data.loc.z-0.5, data.loc[4], 0, 1, true)
|
||||
beanseat = data.stand
|
||||
sitting = true
|
||||
end
|
||||
while sitting do
|
||||
if sitting then
|
||||
if IsControlJustReleased(0, 202) and IsPedUsingScenario(ped, "PROP_HUMAN_SEAT_CHAIR_MP_PLAYER") then
|
||||
sitting = false
|
||||
ClearPedTasks(ped)
|
||||
if beanseat then SetEntityCoords(ped, beanseat) end
|
||||
beanseat = nil
|
||||
end
|
||||
end
|
||||
Wait(5) if not IsPedUsingScenario(ped, "PROP_HUMAN_SEAT_CHAIR_MP_PLAYER") then sitting = false end
|
||||
end
|
||||
end)
|
||||
|
||||
Config.Chairs = {}
|
||||
for k, v in pairs(Config.Locations) do
|
||||
if v.zoneEnable and k == "beangabzlegion" then
|
||||
--STOOLS
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(124.5, -1032.41, 29.27+0.3, 160.0), stand = vec3(124.7, -1031.93, 29.28-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(122.95, -1032.34, 29.28+0.3, 205.0), stand = vec3(122.79, -1031.92, 29.28-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(122.19, -1033.4, 29.28+0.3, 250.0), stand = vec3(121.61, -1033.26, 29.28-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(121.76, -1034.44, 29.28+0.3, 250.0), stand = vec3(121.31, -1034.31, 29.28-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(119.12, -1041.75, 29.28+0.3, 250.0), stand = vec3(118.58, -1041.51, 29.28-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(118.74, -1042.75, 29.28+0.3, 235.0), stand = vec3(118.33, -1042.5, 29.28-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(118.71, -1044.01, 29.28+0.3, 295.0), stand = vec3(118.27, -1044.17, 29.28-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(119.9, -1044.98, 29.28+0.3, 340.0), stand = vec3(119.69, -1045.51, 29.28-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(122.45, -1046.87, 29.28+0.3, 86.0), }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(121.74, -1048.66, 29.28+0.3, 18.0), stand = vec3(121.35, -1048.28, 29.28-0.5) }
|
||||
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(117.91, -1047.8, 29.28+0.3, 18.0), }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(116.28, -1047.11, 29.28+0.3, 317.0), }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(125.15, -1029.07, 29.28+0.3, 118.0), stand = vec3(125.21, -1029.64, 29.28-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(123.61, -1028.61, 29.28+0.3, 188.0), stand = vec3(123.35, -1029.11, 29.28-0.5) }
|
||||
|
||||
--SEATING
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(120.67, -1027.8, 29.28, 165.0), }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(119.02, -1028.51, 29.28, 245.0), }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(119.15, -1031.58, 29.28, 175.0), }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(117.74, -1032.55, 29.28, 250.0), }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(117.39, -1033.47, 29.28, 250.0), }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(117.04, -1034.42, 29.28, 250.0), }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(117.66, -1035.97, 29.28, 335.0), }
|
||||
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(113.5, -1044.37, 28.92, 265.0), }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(114.34, -1045.99, 28.92, 325.0), }
|
||||
end
|
||||
if v.zoneEnable and k == "beanunclejust" then
|
||||
--STOOLS
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-633.64, 234.67, 81.88+0.2, 92.0), stand = vec3(-633.09, 234.73, 81.88-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-633.75, 235.63, 81.88+0.2, 92.0), stand = vec3(-633.33, 235.65, 81.88-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-634.03, 236.75, 81.88+0.2, 182.0), stand = vec3(-633.18, 236.42, 81.88-0.5) }
|
||||
|
||||
--Downstairs
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-631.62, 236.27, 81.88, 275.0), }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-628.6, 236.73, 81.88, 95.0), }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-626.22, 235.22, 81.88, 300.0), }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-624.47, 234.09, 81.88, 355.0), }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-622.67, 235.11, 81.88, 55.0), }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-626.85, 229.71, 81.88, 0.0), }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-625.7, 229.69, 81.88, 0.0), }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-624.6, 231.15, 81.88, 90.0), }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-618.61, 232.89, 81.88, 145.0), }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-620.51, 230.18, 81.88, 320.0), }
|
||||
|
||||
--Upstairs
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-623.7, 233.62, 86.33, 130.0), stand = vec3(-623.28, 234.17, 86.33-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-625.21, 233.45, 86.33, 220.0), stand = vec3(-625.67, 233.94, 86.33-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-625.64, 232.02, 86.33, 310.0), stand = vec3(-626.22, 231.48, 86.33-0.5) }
|
||||
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-626.82, 231.09, 86.33, 130.0), stand = vec3(-626.22, 231.48, 86.33-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-628.39, 230.97, 86.33, 220.0), stand = vec3(-628.8, 231.53, 86.33-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-628.82, 229.51, 86.33, 310.0), stand = vec3(-629.37, 229.13, 86.33-0.5) }
|
||||
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-624.59, 237.18, 86.33, 120.0), stand = vec3(-624.06, 237.63, 86.33-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-625.31, 235.85, 86.33, 30.0), stand = vec3(-624.83, 235.34, 86.33-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-626.81, 236.01, 86.33, 300.0), stand = vec3(-627.37, 235.66, 86.33-0.5) }
|
||||
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-633.4, 232.16, 86.33, 150.0), stand = vec3(-632.88, 231.85, 86.33-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-633.4, 230.55, 86.33, 60.0), stand = vec3(-632.9, 230.19, 86.33-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-634.76, 229.97, 86.33, 330.0), stand = vec3(-634.17, 229.69, 86.33-0.5) }
|
||||
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-633.4, 227.58, 86.33, 85.0), stand = vec3(-632.73, 227.6, 86.33-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-634.7, 226.83, 86.33, 355.0), stand = vec3(-634.97, 226.02, 86.33-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-635.75, 227.74, 86.33, 265.0), stand = vec3(-634.97, 226.02, 86.33-0.5) }
|
||||
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-635.67, 225.62, 86.33, 180.0), stand = vec3(-634.97, 226.02, 86.33-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-634.9, 224.33, 86.33, 90.0), stand = vec3(-634.29, 224.31, 86.33-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-635.68, 223.1, 86.33, 0.0), stand = vec3(-634.99, 223.01, 86.33-0.5) }
|
||||
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-633.07, 222.61, 86.33, 0.0), }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-631.93, 222.61, 86.33, 0.0), }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-630.54, 223.7, 86.33, 75.0), }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-630.29, 224.82, 86.33, 75.0), }
|
||||
--UPPER BALCONY
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-636.72, 231.8, 86.08, 4.0), stand = vec3(-635.86, 231.68, 86.07-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-636.77, 233.65, 86.06, 184.0), stand = vec3(-635.83, 233.58, 86.06-0.5) }
|
||||
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-634.11, 237.08, 86.06, 300.0), stand = vec3(-633.6, 236.49, 86.06-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-632.86, 236.82, 86.06, 30.0), stand = vec3(-633.6, 236.49, 86.06-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-632.59, 238.04, 86.05, 120.0), stand = vec3(-633.11, 238.64, 86.06-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-633.83, 238.35, 86.06, 210.0), stand = vec3(-633.11, 238.64, 86.06-0.5) }
|
||||
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-630.14, 240.02, 86.04, 15.0), stand = vec3(-630.85, 239.81, 86.05-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-631.28, 240.54, 86.05, 285.0), stand = vec3(-630.85, 239.81, 86.05-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-629.63, 241.17, 86.04, 105.0), stand = vec3(-629.39, 240.55, 86.05-0.5) }
|
||||
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-627.25, 241.95, 86.04, 285.0), stand = vec3(-626.88, 241.24, 86.03-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-626.05, 241.39, 86.03, 15.0), stand = vec3(-626.88, 241.24, 86.03-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-625.36, 242.58, 86.01, 105.0), stand = vec3(-625.29, 241.79, 86.01-0.5) }
|
||||
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-622.15, 242.37, 86.01, 260.0), stand = vec3(-622.11, 241.57, 86.01-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-621.37, 241.42, 86.01, 350.0), stand = vec3(-622.11, 241.57, 86.01-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-620.39, 242.2, 86.01, 80.0), stand = vec3(-620.5, 241.43, 86.01-0.5) }
|
||||
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-624.04, 238.96, 86.01, 120.0), stand = vec3(-624.4, 239.71, 86.01-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-625.59, 238.09, 86.02, 300.0), stand = vec3(-626.01, 238.73, 86.02-0.5) }
|
||||
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-627.76, 237.1, 86.03, 120.0), stand = vec3(-628.09, 237.79, 86.03-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-629.32, 236.25, 86.04, 300.0), stand = vec3(-629.75, 236.94, 86.03-0.5) }
|
||||
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-627.61, 227.61, 81.88, 180.0), stand = vec3(-628.61, 227.59, 81.88-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-628.46, 226.75, 81.88, 270.0), stand = vec3(-628.61, 227.59, 81.88-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-628.45, 225.91, 81.88, 270.0), stand = vec3(-628.31, 225.18, 81.88-0.5) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(-627.53, 224.93, 81.88, 0.0), stand = vec3(-628.31, 225.18, 81.88-0.5) }
|
||||
end
|
||||
if v.zoneEnable and k == "beanrflx" then
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(279.53, -969.18, 29.42, 0.0), stand = vec3(280.63, -969.1, 29.42) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(279.51, -966.31, 29.42, 200.0) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(283.36, -971.17, 29.42, 0.0), stand = vec3(282.39, -970.87, 29.42) }
|
||||
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(283.31, -968.57, 29.42, 180.0), stand = vec3(282.11, -968.12, 29.42) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(283.3, -967.58, 29.42, 0.0), stand = vec3(282.11, -968.12, 29.42) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(283.31, -964.97, 29.42, 180.0), stand = vec3(282.05, -965.13, 29.42) }
|
||||
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(287.83, -974.44, 29.42, 90.0) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(287.83, -975.25, 29.42, 90.0) }
|
||||
Config.Chairs[#Config.Chairs+1] = { coords = vec4(287.83, -976.10, 29.42, 90.0) }
|
||||
end
|
||||
end
|
||||
|
||||
AddEventHandler('onResourceStop', function(r) if r ~= GetCurrentResourceName() then return end
|
||||
if GetResourceState("qb-target") == "started" or GetResourceState("ox_target") == "started" then
|
||||
for k, v in pairs(Chairs) do exports['qb-target']:RemoveZone(k) end
|
||||
end
|
||||
end)
|
343
resources/[jims]/jim-beanmachine/client/client.lua
Normal file
@ -0,0 +1,343 @@
|
||||
local QBCore = exports[Config.Core]:GetCoreObject()
|
||||
|
||||
PlayerJob = {}
|
||||
local Targets, Props, CraftLock = {}, {}, false
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
|
||||
QBCore.Functions.GetPlayerData(function(PlayerData) PlayerJob = PlayerData.job if PlayerJob.onduty then for k, v in pairs(Config.Locations) do if PlayerData.job.name == v.job then TriggerServerEvent("QBCore:ToggleDuty") end end end end)
|
||||
end)
|
||||
RegisterNetEvent('QBCore:Client:OnJobUpdate', function(JobInfo) PlayerJob = JobInfo onDuty = PlayerJob.onduty end)
|
||||
RegisterNetEvent('QBCore:Client:SetDuty', function(duty) onDuty = duty end)
|
||||
AddEventHandler('onResourceStart', function(r) if GetCurrentResourceName() ~= r then return end
|
||||
QBCore.Functions.GetPlayerData(function(PlayerData) PlayerJob = PlayerData.job for k, v in pairs(Config.Locations) do if PlayerData.job.name == v.job then onDuty = PlayerJob.onduty end end end)
|
||||
end)
|
||||
|
||||
CreateThread(function()
|
||||
for k, v in pairs(Config.Locations) do
|
||||
local bossroles = {}
|
||||
for grade, info in pairs(QBCore.Shared.Jobs[v.job].grades) do
|
||||
if info.isboss then
|
||||
if bossroles[v.job] then
|
||||
if bossroles[v.job] > tonumber(grade) then bossroles[v.job] = tonumber(grade) end
|
||||
else bossroles[v.job] = tonumber(grade) end
|
||||
end
|
||||
end
|
||||
if v.zoneEnable then
|
||||
makeBlip({ coords = v.blip, sprite = v.blipsprite, col = v.blipcolor, scale = v.blipscale, disp = v.blipdisp, category = v.blipcat, name = v.label })
|
||||
if v.zones then
|
||||
JobLocation = PolyZone:Create(v.zones, { name = v.label, debugPoly = Config.Debug })
|
||||
JobLocation:onPlayerInOut(function(isPointInside)
|
||||
if PlayerJob.name == v.job then
|
||||
if v.autoClock and v.autoClock.enter then if isPointInside and not onDuty then TriggerServerEvent("QBCore:ToggleDuty") end end
|
||||
if v.autoClock and v.autoClock.exit then if not isPointInside and onDuty then TriggerServerEvent("QBCore:ToggleDuty") end end
|
||||
end
|
||||
end)
|
||||
end
|
||||
local propTable = {}
|
||||
if k == "beangabzlegion" then
|
||||
Targets["BeanWash"] =
|
||||
exports['qb-target']:AddBoxZone("BeanWash", vec3(123.73, -1039.24, 29.28-0.5), 1.2, 0.6, { name="BeanWash", heading = 340.0, debugPoly=Config.Debug, minZ=28.88, maxZ=29.68 },
|
||||
{ options = { { event = "jim-beanmachine:washHands", icon = "fas fa-hand-holding-water", label = Loc[Config.Lan].targetinfo["wash_hands"], job = v.job, coords = vec3(123.73, -1039.24, 29.28) }, }, distance = 1.5 })
|
||||
Targets["BeanCounter"] =
|
||||
exports['qb-target']:AddBoxZone("BeanCounter", vec3(120.54, -1040.74, 29.28-1), 0.6, 0.4, { name="BeanCounter", heading = 340.0, debugPoly=Config.Debug, minZ=29.08, maxZ=30.08 },
|
||||
{ options = { { event = "jim-beanmachine:Stash", icon = "fas fa-mug-saucer", label = Loc[Config.Lan].targetinfo["open_counter"], stash = "Counter", coords = vec3(120.54, -1040.74, 29.28) }, }, distance = 2.0 })
|
||||
Targets["BeanCounter2"] =
|
||||
exports['qb-target']:AddBoxZone("BeanCounter2", vec3(121.85, -1037.08, 29.28-1), 0.6, 0.4, { name="BeanCounter2", heading = 340.0, debugPoly=Config.Debug, minZ=29.08, maxZ=30.08},
|
||||
{ options = { { event = "jim-beanmachine:Stash", icon = "fas fa-mug-saucer", label = Loc[Config.Lan].targetinfo["open_counter"], stash = "Counter2", coords = vec3(121.85, -1037.08, 29.28) }, }, distance = 2.0 })
|
||||
|
||||
Targets["BeanReceipt"] =
|
||||
exports['qb-target']:AddBoxZone("BeanReceipt", vec3(120.73, -1040.09, 29.28), 0.6, 0.6, { name="BeanReceipt", heading = 340.0, debugPoly=Config.Debug, minZ=29.08, maxZ=29.88 },
|
||||
{ options = { { event = "jim-payments:client:Charge", icon = "fas fa-credit-card", label = Loc[Config.Lan].targetinfo["charge_customer"], job = v.job,
|
||||
img = "<center><p><img src=https://static.wikia.nocookie.net/gtawiki/images/f/fc/TheBeanMachine-GTA4-logo.png width=100px></p>"
|
||||
} }, distance = 2.0 })
|
||||
Targets["BeanReceipt2"] =
|
||||
exports['qb-target']:AddBoxZone("BeanReceipt2",vec3(122.0, -1036.51, 29.28), 0.6, 0.6, { name="BeanReceipt2", heading = 340.0, debugPoly=Config.Debug, minZ=29.08, maxZ=29.88 },
|
||||
{ options = { { event = "jim-payments:client:Charge", icon = "fas fa-credit-card", label = Loc[Config.Lan].targetinfo["charge_customer"], job = v.job,
|
||||
img = "<center><p><img src=https://static.wikia.nocookie.net/gtawiki/images/f/fc/TheBeanMachine-GTA4-logo.png width=100px></p>"
|
||||
} }, distance = 2.0 })
|
||||
|
||||
Targets["BeanFridge"] =
|
||||
exports['qb-target']:AddBoxZone("BeanFridge", vec3(124.51, -1037.97, 29.28), 0.85, 0.6, { name="BeanFridge", heading = 340.0, debugPoly=Config.Debug, minZ=29.28, maxZ=30.08 },
|
||||
{ options = { { event = "jim-beanmachine:Shop", icon = "fas fa-archive", label = Loc[Config.Lan].targetinfo["open_storage"], job = v.job, shop = Config.FoodItems, shopname = "BeanFridge", coords = vec3(124.51, -1037.97, 29.28) }, }, distance = 1.5 })
|
||||
Targets["BeanFridge2"] =
|
||||
exports['qb-target']:AddBoxZone("BeanFridge2", vec3(123.5, -1040.74, 29.28), 0.9, 0.6, { name="BeanFridge2", heading = 340.0, debugPoly=Config.Debug, minZ=29.28, maxZ=30.08 },
|
||||
{ options = { { event = "jim-beanmachine:Shop", icon = "fas fa-archive", label = Loc[Config.Lan].targetinfo["open_storage"], job = v.job, shop = Config.FoodItems, shopname = "BeanFridge2", coords = vec3(123.5, -1040.74, 29.28) }, }, distance = 1.5 })
|
||||
|
||||
Targets["BeanDrink"] =
|
||||
exports['qb-target']:AddBoxZone("BeanDrink", vec3(124.56, -1036.88, 29.28), 0.7, 0.4, { name="BeanDrink", heading = 340.0, debugPoly=Config.Debug, minZ=29.08, maxZ=29.88 },
|
||||
{ options = { { event = "jim-beanmachine:Crafting", icon = "fas fa-mug-hot", label = Loc[Config.Lan].targetinfo["prepare_coffee"], job = v.job, craftable = Crafting.Drinks, header = Loc[Config.Lan].menu["drink_menu"], coords = vec3(124.56, -1036.88, 29.28) }, }, distance = 2.0 })
|
||||
Targets["BeanDrink2"] =
|
||||
exports['qb-target']:AddBoxZone("BeanDrink2", vec3(122.93, -1041.68, 29.28), 0.7, 0.6, { name="BeanDrink2", heading = 340.0, debugPoly=Config.Debug, minZ=29.08, maxZ=29.88 },
|
||||
{ options = { { event = "jim-beanmachine:Crafting", icon = "fas fa-mug-hot", label = Loc[Config.Lan].targetinfo["prepare_coffee"], job = v.job, craftable = Crafting.Drinks, header = Loc[Config.Lan].menu["drink_menu"], coords = vec3(122.93, -1041.68, 29.28) }, }, distance = 2.0 })
|
||||
|
||||
Targets["BeanSlush"] =x
|
||||
exports['qb-target']:AddBoxZone("BeanSlush", vec3(126.07, -1036.59, 29.28), 0.6, 0.6, { name="BeanSlush", heading = 340.0, debugPoly=Config.Debug, minZ=29.08, maxZ=30.08 },
|
||||
{ options = { { event = "jim-beanmachine:Crafting", icon = "fas fa-cocktail", label = Loc[Config.Lan].targetinfo["prepare_slush"], job = v.job, craftable = Crafting.Slush, header = Loc[Config.Lan].menu["slush_menu"], coords = vec3(126.07, -1036.59, 29.28) }, }, distance = 2.0 })
|
||||
|
||||
Targets["BeanSoda"] =
|
||||
exports['qb-target']:AddBoxZone("BeanSoda", vec3(123.56, -1042.75, 29.28), 0.6, 1.4, { name="BeanSoda", heading = 340.0, debugPoly=Config.Debug, minZ=29.08, maxZ=29.88 },
|
||||
{ options = { { event = "jim-beanmachine:Shop", icon = "fas fa-archive", label = Loc[Config.Lan].targetinfo["grab_soda"], job = v.job, shop = Config.SodaItems, shopname = "BeanSoda", coords = vec3(123.56, -1042.75, 29.28) }, }, distance = 2.0 })
|
||||
|
||||
Targets["BeanDonut"] =
|
||||
exports['qb-target']:AddBoxZone("BeanDonut", vec3(121.4, -1038.43, 29.28), 1.45, 0.6, { name="BeanDonut", heading = 340.0, debugPoly=Config.Debug, minZ=29.28, maxZ=29.88 },
|
||||
{ options = { { event = "jim-beanmachine:Shop", icon = "fas fa-circle-dot", label = Loc[Config.Lan].targetinfo["grab_food"], job = v.job, shop = Config.DesertItems, shopname = "BeanDonut", coords = vec3(121.4, -1038.43, 29.28) },
|
||||
{ event = "jim-beanmachine:Stash", icon = "fas fa-archive", label = Loc[Config.Lan].targetinfo["open_stash"], job = v.job, stash = "LegionStash", coords = vec3(121.4, -1038.43, 29.28) }, }, distance = 2.0 })
|
||||
|
||||
Targets["BeanClockin"] =
|
||||
exports['qb-target']:AddBoxZone("BeanClockin", vec3(126.94, -1035.84, 29.28), 1.2, 0.2, { name="BeanClockin", heading = 340.0, debugPoly=Config.Debug, minZ=29.28, maxZ=31.28 },
|
||||
{ options = { { type = "server", event = "QBCore:ToggleDuty", icon = "fas fa-user-check", label = Loc[Config.Lan].targetinfo["toggle_duty"], job = v.job },
|
||||
{ event = "qb-bossmenu:client:OpenMenu", icon = "fas fa-list", label = Loc[Config.Lan].targetinfo["open_bossmenu"], job = bossroles, },
|
||||
}, distance = 2.0 })
|
||||
end
|
||||
if k == "beanunclejust" then
|
||||
--Cereal Boxes
|
||||
CreateModelHide(vec3(-636.56, 235.83, 82.43), 1.0, -598185919, true) CreateModelHide(vec3(-636.56, 235.83, 82.43), 1.0, 714696561, true)
|
||||
CreateModelHide(vec3(-636.56, 235.83, 82.43), 1.0, 1241647493, true) CreateModelHide(vec3(-636.56, 235.83, 82.43), 1.0, 2141353157, true)
|
||||
|
||||
CreateModelHide(vec3(-634.28, 235.29, 83.12), 1.5, 270388964, true) CreateModelHide(vec3(-634.28, 235.29, 83.12), 1.5, 974883178, true)
|
||||
CreateModelHide(vec3(-634.28, 235.29, 83.12), 1.5, -85890288, true) CreateModelHide(vec3(-635.73, 235.3, 81.88), 1.5, -1281587804, true)
|
||||
CreateModelHide(vec3(-633.47, 233.44, 81.88+1.0), 1.5, 1503218008, true)
|
||||
|
||||
propTable[#propTable+1] = { prop = "prop_till_03", coords = vec4(-634.38, 235.29, 83.12, 285.0)}
|
||||
propTable[#propTable+1] = { prop = "prop_food_tray_01", coords = vec4(-634.28, 234.69, 83.12, 95.0)}
|
||||
propTable[#propTable+1] = { prop = "prop_slush_dispenser", coords = vec4(-636.56, 235.83, 82.43+0.91, 90.0)}
|
||||
|
||||
Targets["UBeanCounter"] =
|
||||
exports['qb-target']:AddBoxZone("UBeanCounter", vec3(-634.27, 234.69, 81.88), 0.55, 0.4, { name="UBeanCounter", heading = 5.0, debugPoly=Config.Debug, minZ=81.93, maxZ=82.48 },
|
||||
{ options = { { event = "jim-beanmachine:Stash", icon = "fas fa-mug-saucer", label = Loc[Config.Lan].targetinfo["open_counter"], stash = "UCounter", coords = vec3(-634.27, 234.69, 81.88) }, }, distance = 2.0 })
|
||||
Targets["UBeanReceipt"] =
|
||||
exports['qb-target']:AddBoxZone("UBeanReceipt", vec3(-634.38, 235.3, 81.88), 0.4, 0.5, { name="UBeanReceipt", heading = 15.0, debugPoly=Config.Debug, minZ=82.08, maxZ=82.68 },
|
||||
{ options = { { event = "jim-payments:client:Charge", icon = "fas fa-credit-card", label = Loc[Config.Lan].targetinfo["charge_customer"], job = v.job,
|
||||
img = "<center><p><img src=https://static.wikia.nocookie.net/gtawiki/images/f/fc/TheBeanMachine-GTA4-logo.png width=100px></p>"
|
||||
} }, distance = 2.0 })
|
||||
Targets["UBeanDrink"] =
|
||||
exports['qb-target']:AddBoxZone("UBeanDrink", vec3(-635.7, 236.55, 81.88), 0.6, 1.0, { name="UBeanDrink", heading = 1.0, debugPoly=Config.Debug, minZ=81.88, maxZ=82.68 },
|
||||
{ options = { { event = "jim-beanmachine:Crafting", icon = "fas fa-mug-hot", label = Loc[Config.Lan].targetinfo["prepare_coffee"], job = v.job, craftable = Crafting.Drinks, header = Loc[Config.Lan].menu["drink_menu"], coords = vec3(-635.7, 236.55, 81.88) }, }, distance = 2.0 })
|
||||
Targets["UBeanDrink2"] =
|
||||
exports['qb-target']:AddBoxZone("UBeanDrink2", vec3(-627.68, 222.8, 81.88), 0.6, 0.8, { name="UBeanDrink2", heading = 0.0, debugPoly=Config.Debug, minZ=81.88, maxZ=82.68 },
|
||||
{ options = { { event = "jim-beanmachine:Crafting", icon = "fas fa-mug-hot", label = Loc[Config.Lan].targetinfo["prepare_coffee"], job = v.job, craftable = Crafting.Drinks, header = Loc[Config.Lan].menu["drink_menu"], coords = vec3(-627.68, 222.8, 81.88) }, }, distance = 2.0 })
|
||||
Targets["UBeanFridge"] =
|
||||
exports['qb-target']:AddBoxZone("UBeanFridge", vec3(-635.51, 233.23, 81.88-1), 0.4, 1.6, { name="UBeanFridge", heading = 339.0, debugPoly=Config.Debug, minZ=80.88, maxZ=83.08 },
|
||||
{ options = { { event = "jim-beanmachine:Shop", icon = "fas fa-archive", label = Loc[Config.Lan].targetinfo["open_shop"], job = v.job, shop = Config.FoodItems, coords = vec3(-635.51, 233.23, 81.88), shopname = "UBeanFridge", },
|
||||
{ event = "jim-beanmachine:Stash", icon = "fas fa-archive", label = Loc[Config.Lan].targetinfo["open_stash"], job = v.job, stash = "UStash", coords = vec3(-635.51, 233.23, 81.88) }, }, distance = 1.5 })
|
||||
Targets["UBeanSlush"] =
|
||||
exports['qb-target']:AddBoxZone("UBeanSlush", vec3(-636.52, 235.81, 81.88), 0.5, 0.5, { name="UBeanSlush", heading = 1.0, debugPoly=Config.Debug, minZ=82.28, maxZ=83.08 },
|
||||
{ options = { { event = "jim-beanmachine:Crafting", icon = "fas fa-cocktail", label = Loc[Config.Lan].targetinfo["prepare_slush"], job = v.job, craftable = Crafting.Slush, header = Loc[Config.Lan].menu["slush_menu"], coords = vec3(-636.52, 235.81, 81.88) }, }, distance = 2.0 })
|
||||
Targets["UBeanSoda"] =
|
||||
exports['qb-target']:AddBoxZone("UBeanSoda", vec3(-636.74, 234.86, 81.88-1), 2.6, 0.4, { name="UBeanSoda", heading = 1.0, debugPoly=Config.Debug, minZ=80.88, maxZ=82.08 },
|
||||
{ options = { { event = "jim-beanmachine:Shop", icon = "fas fa-archive", label = Loc[Config.Lan].targetinfo["grab_soda"], job = v.job, shop = Config.SodaItems, shopname = "UBeanSoda", coords = vec3(-636.74, 234.86, 81.88) }, }, distance = 2.0 })
|
||||
Targets["UBeanDonut"] =
|
||||
exports['qb-target']:AddBoxZone("UBeanDonut", vec3(-636.62, 234.98, 81.88), 0.6, 0.6, { name="UBeanDonut", heading = 1.0, debugPoly=Config.Debug, minZ=82.28, maxZ=82.88 },
|
||||
{ options = { { event = "jim-beanmachine:Shop", icon = "fas fa-circle-dot", label = Loc[Config.Lan].targetinfo["grab_food"], job = v.job, shop = Config.DesertItems, shopname = "UBeanDonut", coords = vec3(-636.62, 234.98, 81.88) }, }, distance = 2.0 })
|
||||
Targets["UBeanWash"] =
|
||||
exports['qb-target']:AddBoxZone("UBeanWash", vec3(-621.67, 226.77, 81.88-1), 1.6, 0.6, { name="BeanWash", heading = 0.0, debugPoly=Config.Debug, minZ=80.88, maxZ=82.68 },
|
||||
{ options = { { event = "jim-beanmachine:washHands", icon = "fas fa-hand-holding-water", label = Loc[Config.Lan].targetinfo["wash_hands"], job = v.job, coords = vec3(-621.67, 226.77, 81.88) }, }, distance = 1.5 })
|
||||
Targets["UBeanWash2"] =
|
||||
exports['qb-target']:AddBoxZone("UBeanWash2", vec3(-630.71, 222.83, 81.88-1), 0.7, 1.4, { name="UBeanWash2", heading = 0.0, debugPoly=Config.Debug, minZ=80.88, maxZ=82.68 },
|
||||
{ options = { { event = "jim-beanmachine:washHands", icon = "fas fa-hand-holding-water", label = Loc[Config.Lan].targetinfo["wash_hands"], job = v.job, coords = vec3(-630.71, 222.83, 81.88) }, }, distance = 1.5 })
|
||||
|
||||
Targets["UBeanClockin"] =
|
||||
exports['qb-target']:AddBoxZone("UBeanClockin", vec3(-635.89, 227.12, 81.88), 1.6, 0.2, { name="UBeanClockin", heading = 0.0, debugPoly=Config.Debug, minZ=81.68, maxZ=82.93 },
|
||||
{ options = { { type = "server", event = "QBCore:ToggleDuty", icon = "fas fa-user-check", label = Loc[Config.Lan].targetinfo["toggle_duty"], job = v.job },
|
||||
{ event = "qb-bossmenu:client:OpenMenu", icon = "fas fa-list", label = "Åben ledermenu", job = bossroles, },
|
||||
}, distance = 2.0 })
|
||||
end
|
||||
if k == "beanrflx" then
|
||||
Targets["flxClockin"] =
|
||||
exports['qb-target']:AddBoxZone("flxClockin", vec3(284.84, -978.75, 29.42-0.3), 0.5, 0.5, { name="flxClockin", heading = 343.0, debugPoly=Config.Debug, minZ=29.02, maxZ=29.62 },
|
||||
{ options = { { type = "server", event = "QBCore:ToggleDuty", icon = "fas fa-user-check", label = Loc[Config.Lan].targetinfo["toggle_duty"], job = v.job },
|
||||
{ event = "qb-bossmenu:client:OpenMenu", icon = "fas fa-list", label = "Åben ledermenu", job = bossroles, },
|
||||
}, distance = 2.0 })
|
||||
Targets["flxReceipt"] =
|
||||
exports['qb-target']:AddBoxZone("flxReceipt", vec3(280.99, -972.57, 29.42), 0.4, 0.5, { name="flxReceipt", heading = 90.0, debugPoly=Config.Debug, minZ=29.42, maxZ=30.22 },
|
||||
{ options = { { event = "jim-payments:client:Charge", icon = "fas fa-credit-card", label = Loc[Config.Lan].targetinfo["charge_customer"], job = v.job,
|
||||
img = "<center><p><img src=https://static.wikia.nocookie.net/gtawiki/images/f/fc/TheBeanMachine-GTA4-logo.png width=100px></p>"
|
||||
} }, distance = 2.0 })
|
||||
Targets["flxCounter"] =
|
||||
exports['qb-target']:AddBoxZone("flxCounter", vec3(280.50, -972.54, 30.29-1), 0.55, 0.7, { name="flxCounter", heading = 90.0, debugPoly=Config.Debug, minZ=29.42, maxZ=30.02 },
|
||||
{ options = { { event = "jim-beanmachine:Stash", icon = "fas fa-mug-saucer", label = Loc[Config.Lan].targetinfo["open_counter"], stash = "flxCounter", coords = vec3(280.50, -972.54, 30.29) }, }, distance = 2.0 })
|
||||
Targets["flxBeanSlush"] =
|
||||
exports['qb-target']:AddBoxZone("flxBeanSlush", vec3(278.92, -972.6, 30.62-1), 0.5, 0.5, { name="flxBeanSlush", heading = 90.0, debugPoly=Config.Debug, minZ=29.42, maxZ=30.52 },
|
||||
{ options = { { event = "jim-beanmachine:Crafting", icon = "fas fa-cocktail", label = Loc[Config.Lan].targetinfo["prepare_slush"], job = v.job, craftable = Crafting.Slush, header = "Slush Menu", coords = vec3(278.92, -972.6, 30.62) }, }, distance = 2.0 })
|
||||
Targets["flxBeanSoda"] =
|
||||
exports['qb-target']:AddBoxZone("flxBeanSoda", vec3(278.87, -973.37, 30.62-1), 0.5, 0.7, { name="flxBeanSoda", heading = 90.0, debugPoly=Config.Debug, minZ=29.42, maxZ=30.22 },
|
||||
{ options = { { event = "jim-beanmachine:Shop", icon = "fas fa-archive", label = Loc[Config.Lan].targetinfo["grab_soda"], job = v.job, shop = Config.SodaItems, shopname = "flxBeanSoda", coords = vec3(278.87, -973.37, 30.62) }, }, distance = 2.0 })
|
||||
|
||||
Targets["flxBeanDonut"] =
|
||||
exports['qb-target']:AddBoxZone("flxBeanDonut", vec3(279.62, -972.55, 30.62-1), 0.5, 0.7, { name="flxBeanDonut", heading = 90.0, debugPoly=Config.Debug, minZ=29.42, maxZ=30.02 },
|
||||
{ options = { { event = "jim-beanmachine:Shop", icon = "fas fa-circle-dot", label = Loc[Config.Lan].targetinfo["grab_food"], job = v.job, shop = Config.DesertItems, shopname = "flxBeanDonut", coords = vec3(279.62, -972.55, 30.62) },
|
||||
{ event = "jim-beanmachine:Stash", icon = "fas fa-archive", label = Loc[Config.Lan].targetinfo["open_stash"], job = v.job, stash = "flxStash", coords = vec3(279.62, -972.55, 30.62) }, }, distance = 2.0 })
|
||||
Targets["flxBeanDrink"] =
|
||||
exports['qb-target']:AddBoxZone("flxBeanDrink", vec3(279.54, -975.12, 29.42), 0.7, 0.5, { name="flxBeanDrink", heading = 90.0, debugPoly=Config.Debug, minZ=29.42, maxZ=30.22 },
|
||||
{ options = { { event = "jim-beanmachine:Crafting", icon = "fas fa-mug-hot", label = Loc[Config.Lan].targetinfo["prepare_coffee"], job = v.job, craftable = Crafting.Drinks, header = "Drinks Menu", coords = vec3(279.54, -975.12, 29.42) }, }, distance = 2.0 })
|
||||
Targets["flxBeanFridge"] =
|
||||
exports['qb-target']:AddBoxZone("flxBeanFridge", vec3(278.94, -971.89, 29.42-1), 0.85, 0.7, { name="flxBeanFridge", heading = 0.0, debugPoly=Config.Debug, minZ=28.62, maxZ=30.62 },
|
||||
{ options = { { event = "jim-beanmachine:Shop", icon = "fas fa-archive", label = Loc[Config.Lan].targetinfo["open_storage"], job = v.job, shop = Config.FoodItems, shopname = "flxBeanFridge", coords = vec3(278.94, -971.89, 29.42) }, }, distance = 1.5 })
|
||||
|
||||
propTable[#propTable+1] = { prop = "v_res_cakedome", coords = vec4(279.62, -972.55, 30.62, 90.0) }
|
||||
propTable[#propTable+1] = { prop = "prop_slush_dispenser", coords = vec4(278.92, -972.6, 30.62, 90.0) }
|
||||
propTable[#propTable+1] = { prop = "prop_food_bs_soda_01", coords = vec4(278.87, -973.37, 30.62, 90.0) }
|
||||
propTable[#propTable+1] = { prop = "prop_food_tray_01", coords = vec4(280.50, -972.54, 30.625, 0.0) }
|
||||
end
|
||||
for _, prop in pairs(propTable) do makeProp(prop, true, false) end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent('jim-beanmachine:washHands', function(data)
|
||||
QBCore.Functions.Progressbar('hand_washing', Loc[Config.Lan].progressbar["washing_hands"], 5000, false, true, { disableMovement = true, disableCarMovement = false, disableMouse = false, disableCombat = false, },
|
||||
{ animDict = "mp_arresting", anim = "a_uncuff", flags = 8, }, {}, {}, function()
|
||||
triggerNotify(nil, Loc[Config.Lan].success["success_washed_hands"], 'success')
|
||||
end, function() -- Cancel
|
||||
TriggerEvent('inventory:client:busy:status', false) triggerNotify(nil, Loc[Config.Lan].error["cancelled"], 'error')
|
||||
end, "fas fa-hand-holding-droplet")
|
||||
end)
|
||||
|
||||
--[[CRAFTING]]--
|
||||
RegisterNetEvent('jim-beanmachine:Crafting:MakeItem', function(data)
|
||||
if not CraftLock then CraftLock = true else return end
|
||||
local bartime = 5000
|
||||
if (data.amount and data.amount ~= 1) then data.craft["amount"] = data.amount
|
||||
for k, v in pairs(data.craft[data.item]) do data.craft[data.item][k] *= data.amount end
|
||||
bartime *= data.amount bartime *= 0.9
|
||||
end
|
||||
QBCore.Functions.Progressbar('making_food', Loc[Config.Lan].progressbar["making"]..QBCore.Shared.Items[data.item].label, bartime, false, true, { disableMovement = true, disableCarMovement = false, disableMouse = false, disableCombat = false, },
|
||||
{ animDict = "mp_ped_interaction", anim = "handshake_guy_a", flags = 8, }, {}, {}, function()
|
||||
CraftLock = false
|
||||
TriggerServerEvent('jim-beanmachine:Crafting:GetItem', data.item, data.craft)
|
||||
Wait(500)
|
||||
TriggerEvent("jim-beanmachine:Crafting", data)
|
||||
end, function() -- Cancel
|
||||
CraftLock = false
|
||||
TriggerEvent('inventory:client:busy:status', false)
|
||||
end, data.item)
|
||||
end)
|
||||
|
||||
RegisterNetEvent('jim-beanmachine:Crafting', function(data)
|
||||
if CraftLock then return end
|
||||
--if not jobCheck() then return end
|
||||
local Menu = {}
|
||||
if Config.Menu == "qb" then
|
||||
Menu[#Menu + 1] = { header = data.header, txt = "", isMenuHeader = true }
|
||||
Menu[#Menu + 1] = { icon = "fas fa-circle-xmark", header = "", txt = Loc[Config.Lan].menu["close"], params = { event = "" } }
|
||||
end
|
||||
for i = 1, #data.craftable do
|
||||
for k, v in pairs(data.craftable[i]) do
|
||||
if k ~= "amount" then
|
||||
local text = ""
|
||||
setheader = QBCore.Shared.Items[tostring(k)].label
|
||||
if data.craftable[i]["amount"] ~= nil then setheader = setheader.." x"..data.craftable[i]["amount"] end
|
||||
local disable = false
|
||||
local checktable = {}
|
||||
for l, b in pairs(data.craftable[i][tostring(k)]) do
|
||||
if b == 0 or b == 1 then number = "" else number = " x"..b end
|
||||
if not QBCore.Shared.Items[l] then
|
||||
print("^3Error^7: ^2Script can't find ingredient item in QB-Core items.lua - ^1"..l.."^7")
|
||||
return
|
||||
end
|
||||
if Config.Menu == "ox" then text = text..QBCore.Shared.Items[l].label..number.."\n" end
|
||||
if Config.Menu == "qb" then text = text.."- "..QBCore.Shared.Items[l].label..number.."<br>" end
|
||||
settext = text
|
||||
checktable[l] = HasItem(l, b)
|
||||
end
|
||||
for _, v in pairs(checktable) do if v == false then disable = true break end end
|
||||
if not disable then setheader = setheader.." ✔️" end
|
||||
local event = "jim-beanmachine:Crafting:MakeItem"
|
||||
if Config.MultiCraft then event = "jim-beanmachine:Crafting:MultiCraft" end
|
||||
Menu[#Menu + 1] = {
|
||||
disabled = disable,
|
||||
icon = "nui://"..Config.img..QBCore.Shared.Items[tostring(k)].image,
|
||||
header = setheader, txt = settext, --qb-menu
|
||||
params = { event = event, args = { item = k, craft = data.craftable[i], craftable = data.craftable, header = data.header } }, -- qb-menu
|
||||
title = setheader, description = settext, -- ox_lib
|
||||
event = event, args = { item = k, craft = data.craftable[i], craftable = data.craftable, header = data.header }, -- ox_lib
|
||||
}
|
||||
settext, setheader = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
if Config.Menu == "ox" then exports.ox_lib:registerContext({id = 'Crafting', title = data.header, position = 'top-right', options = Menu }) exports.ox_lib:showContext("Crafting")
|
||||
elseif Config.Menu == "qb" then exports['qb-menu']:openMenu(Menu) end
|
||||
lookEnt(data.coords)
|
||||
end)
|
||||
|
||||
RegisterNetEvent('jim-beanmachine:Crafting:MultiCraft', function(data)
|
||||
local success = Config.MultiCraftAmounts local Menu = {}
|
||||
for k in pairs(success) do success[k] = true
|
||||
for l, b in pairs(data.craft[data.item]) do
|
||||
local has = HasItem(l, (b * k)) if not has then success[k] = false break else success[k] = true end
|
||||
end
|
||||
end
|
||||
if Config.Menu == "qb" then Menu[#Menu + 1] = { header = data.header, txt = "", isMenuHeader = true } end
|
||||
Menu[#Menu + 1] = { icon = "fas fa-arrow-left", title = Loc[Config.Lan].menu["back"], header = "", txt = Loc[Config.Lan].menu["back"], params = { event = "jim-beanmachine:Crafting", args = data }, event = "jim-beanmachine:Crafting", args = data }
|
||||
for k in pairsByKeys(success) do
|
||||
Menu[#Menu + 1] = {
|
||||
disabled = not success[k],
|
||||
icon = "nui://"..Config.img..QBCore.Shared.Items[data.item].image, header = QBCore.Shared.Items[data.item].label.." [x"..k.."]", title = QBCore.Shared.Items[data.item].label.." [x"..k.."]",
|
||||
event = "jim-beanmachine:Crafting:MakeItem", args = { item = data.item, craft = data.craft, craftable = data.craftable, header = data.header, anim = data.anim, amount = k },
|
||||
params = { event = "jim-beanmachine:Crafting:MakeItem", args = { item = data.item, craft = data.craft, craftable = data.craftable, header = data.header, anim = data.anim, amount = k } }
|
||||
}
|
||||
end
|
||||
if Config.Menu == "ox" then exports.ox_lib:registerContext({id = 'Crafting', title = data.header, position = 'top-right', options = Menu }) exports.ox_lib:showContext("Crafting")
|
||||
elseif Config.Menu == "qb" then exports['qb-menu']:openMenu(Menu) end
|
||||
end)
|
||||
|
||||
--[[STASH SHOPS]]--
|
||||
RegisterNetEvent('jim-beanmachine:Stash', function(data)
|
||||
--if data.job and not jobCheck() then return end
|
||||
if Config.Inv == "ox" then exports.ox_inventory:openInventory('stash', "beanmachine_"..data.stash) else
|
||||
TriggerEvent("inventory:client:SetCurrentStash", "beanmachine_"..data.stash)
|
||||
TriggerServerEvent("inventory:server:OpenInventory", "stash", "beanmachine_"..data.stash) end
|
||||
lookEnt(data.coords)
|
||||
end)
|
||||
|
||||
RegisterNetEvent('jim-beanmachine:Shop', function(data)
|
||||
--if not jobCheck() then return end
|
||||
local event = "inventory:server:OpenInventory"
|
||||
if Config.JimShop then event = "jim-shops:ShopOpen"
|
||||
elseif Config.Inv == "ox" then exports.ox_inventory:openInventory('shop', { type = data.shopname }) end
|
||||
TriggerServerEvent(event, "shop", "beanmachine", data.shop)
|
||||
lookEnt(data.coords)
|
||||
end)
|
||||
|
||||
-- [[CONSUME]] --
|
||||
local function ConsumeSuccess(itemName, type)
|
||||
ExecuteCommand("e c")
|
||||
toggleItem(false, itemName, 1)
|
||||
if QBCore.Shared.Items[itemName].hunger then
|
||||
TriggerServerEvent("QBCore:Server:SetMetaData", "hunger", QBCore.Functions.GetPlayerData().metadata["hunger"] + QBCore.Shared.Items[itemName].hunger)
|
||||
--TriggerServerEvent("consumables:server:addHunger", QBCore.Functions.GetPlayerData().metadata["hunger"] + QBCore.Shared.Items[itemName].hunger)
|
||||
end
|
||||
if QBCore.Shared.Items[itemName].thirst then
|
||||
TriggerServerEvent("QBCore:Server:SetMetaData", "thirst", QBCore.Functions.GetPlayerData().metadata["thirst"] + QBCore.Shared.Items[itemName].thirst)
|
||||
--TriggerServerEvent("consumables:server:addThirst", QBCore.Functions.GetPlayerData().metadata["thirst"] + QBCore.Shared.Items[itemName].thirst)
|
||||
end
|
||||
if type == "alcohol" then alcoholCount += 1
|
||||
if alcoholCount > 1 and alcoholCount < 4 then TriggerEvent("evidence:client:SetStatus", "alcohol", 200) elseif alcoholCount >= 4 then TriggerEvent("evidence:client:SetStatus", "heavyalcohol", 200) AlienEffect() end
|
||||
end
|
||||
if Config.RewardItem == itemName then toggleItem(true, Config.RewardPool[math.random(1, #Config.RewardPool)], 1) end
|
||||
end
|
||||
|
||||
RegisterNetEvent('jim-beanmachine:client:Consume', function(itemName, type)
|
||||
local emoteTable = {
|
||||
["sprunk"] = "sprunk", ["sprunklight"] = "sprunk", ["ecola"] = "ecola", ["ecolalight"] = "ecola",
|
||||
["ecocoffee"] = "bmcoffee1", ["flusher"] = "bmcoffee2", ["caffeagra"] = "bmcoffee3", ["crisps"] = "crisps",
|
||||
["beandonut"] = "donut2", ["chocolate"] = "egobar",
|
||||
}
|
||||
local progstring, defaultemote = Loc[Config.Lan].progressbar["drinking"], "drink"
|
||||
if type == "food" then progstring = Loc[Config.Lan].progressbar["eating"] defaultemote = "burger" end
|
||||
ExecuteCommand("e "..(emoteTable[itemName] or defaultemote))
|
||||
QBCore.Functions.Progressbar('making_food', progstring..QBCore.Shared.Items[itemName].label.."..", math.random(3000, 6000), false, true, { disableMovement = false, disableCarMovement = false, disableMouse = false, disableCombat = false, },
|
||||
{ animDict = animDictNow, anim = animNow, flags = 8, }, {}, {}, function()
|
||||
ConsumeSuccess(itemName, type)
|
||||
end, function() -- Cancel
|
||||
ExecuteCommand("e c")
|
||||
end, itemName)
|
||||
end)
|
||||
AddEventHandler('onResourceStop', function(r) if r ~= GetCurrentResourceName() then return end
|
||||
if GetResourceState("qb-target") == "started" or GetResourceState("ox_target") == "started" then
|
||||
for k in pairs(Targets) do exports['qb-target']:RemoveZone(k) end
|
||||
for k in pairs(Props) do DeleteEntity(Props[k]) end
|
||||
exports['qb-menu']:closeMenu()
|
||||
end
|
||||
end)
|
133
resources/[jims]/jim-beanmachine/config.lua
Normal file
@ -0,0 +1,133 @@
|
||||
-- If you need support I now have a discord available, it helps me keep track of issues and give better support.
|
||||
|
||||
-- https://discord.gg/xKgQZ6wZvS
|
||||
|
||||
Config = {
|
||||
Debug = false, -- false to remove green boxes
|
||||
Lan = "da", -- change the language
|
||||
img = "ps-inventory/html/images/", -- Change this to your inventory's name and image folder
|
||||
|
||||
Core = "qb-core", -- set this to your core folder
|
||||
Inv = "qb", -- set to "ox" if using OX Inventory
|
||||
Menu = "qb", -- set to "ox" if using ox_lib context menus
|
||||
Notify = "qb",
|
||||
ProgressBar = "qb", -- set to "ox" if using ox_lib progressbar
|
||||
|
||||
JimConsumables = false, -- Enable this to disable this scripts control of food/drink items
|
||||
JimShop = false, -- If true shops will open in jim-shops
|
||||
|
||||
MultiCraft = true,
|
||||
MultiCraftAmounts = { [1], [5], [10] },
|
||||
|
||||
--Simple Toy Reward Support - disabled if JimConsumables are true
|
||||
RewardItem = "", --Set this to the name of an item eg "bento"
|
||||
RewardPool = { -- Set this to the list of items to be given out as random prizes when the item is used - can be more or less items in the list
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
},
|
||||
|
||||
FoodItems = {
|
||||
label = "Køleskab",
|
||||
slots = 8,
|
||||
items = {
|
||||
{ name = "water_bottle", price = 0, amount = 50, info = {}, type = "item", slot = 1, },
|
||||
{ name = "orange", price = 0, amount = 50, info = {}, type = "item", slot = 2, },
|
||||
{ name = "sugar", price = 0, amount = 50, info = {}, type = "item", slot = 3, },
|
||||
{ name = "chickenbreast", price = 0, amount = 50, info = {}, type = "item", slot = 4, },
|
||||
{ name = "rhinohorn", price = 0, amount = 50, info = {}, type = "item", slot = 5, },
|
||||
{ name = "oystershell", price = 0, amount = 50, info = {}, type = "item", slot = 6, },
|
||||
{ name = "milk", price = 0, amount = 50, info = {}, type = "item", slot = 7, },
|
||||
{ name = "beancoffee", price = 0, amount = 50, info = {}, type = "item", slot = 8, },
|
||||
},
|
||||
},
|
||||
DesertItems = {
|
||||
label = "Desert-skab",
|
||||
slots = 6,
|
||||
items = {
|
||||
{ name = "beandonut", price = 0, amount = 50, info = {}, type = "item", slot = 1, },
|
||||
{ name = "chocolate", price = 0, amount = 50, info = {}, type = "item", slot = 2, },
|
||||
{ name = "crisps", price = 0, amount = 50, info = {}, type = "item", slot = 3, },
|
||||
{ name = "watermelon", price = 0, amount = 50, info = {}, type = "item", slot = 4, },
|
||||
{ name = "cheesecake", price = 0, amount = 50, info = {}, type = "item", slot = 5, },
|
||||
{ name = "tosti", price = 0, amount = 50, info = {}, type = "item", slot = 6, },
|
||||
},
|
||||
},
|
||||
SodaItems = {
|
||||
label = "Sodavand",
|
||||
slots = 4,
|
||||
items = {
|
||||
{ name = "ecola", price = 0, amount = 50, info = {}, type = "item", slot = 1, },
|
||||
{ name = "ecolalight", price = 0, amount = 50, info = {}, type = "item", slot = 2, },
|
||||
{ name = "sprunk", price = 0, amount = 50, info = {}, type = "item", slot = 3, },
|
||||
{ name = "sprunklight", price = 0, amount = 50, info = {}, type = "item", slot = 4, },
|
||||
},
|
||||
},
|
||||
Locations = {
|
||||
["beangabzlegion"] = {
|
||||
zoneEnable = false,
|
||||
label = "Bean Machine (Legion)",
|
||||
job = "beanmachine",
|
||||
autoClock = { enter = false, exit = true, },
|
||||
zones = {
|
||||
vec2(137.44329833984, -1019.5242919922),
|
||||
vec2(122.99235534668, -1058.451171875),
|
||||
vec2(101.35326385498, -1048.4799804688),
|
||||
vec2(115.27521514893, -1011.9081420898)
|
||||
},
|
||||
garage = { spawn = vec4(130.93, -1032.04, 28.76, 340.2),
|
||||
out = vec4(129.41, -1031.15, 29.43, 253.32),
|
||||
list = { "panto", } },
|
||||
blip = vec3(120.27, -1038.09, 29.28), blipcolor = 56, blipsprite = 106, blipdisp = 6, blipscale = 0.7, blipcat = nil,
|
||||
},
|
||||
["beanunclejust"] = {
|
||||
zoneEnable = true,
|
||||
label = "Bean Machine (Vinewood)",
|
||||
job = "beanmachine",
|
||||
autoClock = { enter = false, exit = true, },
|
||||
zones = {
|
||||
vec2(-649.89886474609, 259.69918823242),
|
||||
vec2(-611.98547363281, 257.3210144043),
|
||||
vec2(-614.646484375, 203.47846984863),
|
||||
vec2(-649.29040527344, 203.21409606934)
|
||||
},
|
||||
garage = { spawn = vec4(-631.99, 207.03, 73.31, 93.9),
|
||||
out = vec4(-632.39, 209.14, 74.32, 179.94),
|
||||
list = { "panto", } },
|
||||
blip = vec3(-629.63, 234.39, 81.88), blipcolor = 56, blipsprite = 106, blipdisp = 6, blipscale = 0.7, blipcat = nil,
|
||||
},
|
||||
["beanrflx"] = {
|
||||
zoneEnable = true,
|
||||
label = "Bean Machine (Legion)",
|
||||
job = "beanmachine",
|
||||
autoClock = { enter = false, exit = true, },
|
||||
zones = {
|
||||
vec2(271.67, -955.77),
|
||||
vec2(291.9, -954.33),
|
||||
vec2(291.61, -986.73),
|
||||
vec2(261.14, -973.50)
|
||||
},
|
||||
garage = { spawn = vec4(278.17, -956.56, 28.6, 269.1),
|
||||
out = vec4(277.52, -958.44, 29.4, 356.56),
|
||||
list = { "panto", } },
|
||||
blip = vec3(281.54, -965.68, 29.42), blipcolor = 56, blipsprite = 106, blipdisp = 6, blipscale = 0.7, blipcat = nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Crafting = {
|
||||
Slush = {
|
||||
{ ['bigfruit'] = { ['watermelon'] = 1, ['water_bottle'] = 1, ['orange'] = 1, ['sugar'] = 1, }, },
|
||||
},
|
||||
Drinks = {
|
||||
{ ['highnoon'] = { ['beancoffee'] = 1, ['water_bottle'] = 1, ['orange'] = 1, }, },
|
||||
{ ['speedball'] = { ['beancoffee'] = 3, ['sugar'] = 1, }, },
|
||||
{ ['gunkaccino'] = { ['beancoffee'] = 1, ['sugar'] = 2, ['cheesecake'] = 1, }, },
|
||||
{ ['bratte'] = { ['beancoffee'] = 2, ['sugar'] = 5, }, },
|
||||
{ ['flusher'] = { ['beancoffee'] = 1, ['water_bottle'] = 1, ['orange'] = 1, ['chickenbreast'] = 1, }, },
|
||||
{ ['ecocoffee'] = { ['beancoffee'] = 1, ['water_bottle'] = 1, ['milk'] = 1, ['plastic'] = 1, }, },
|
||||
{ ['caffeagra'] = { ['beancoffee'] = 1, ['rhinohorn'] = 2, ['oystershell'] = 1, }, },
|
||||
},
|
||||
}
|
||||
|
||||
Loc = {}
|
11
resources/[jims]/jim-beanmachine/fxmanifest.lua
Normal file
@ -0,0 +1,11 @@
|
||||
name "Jim-BeanMachine"
|
||||
author "Jimathy"
|
||||
version "1.4.4"
|
||||
description "BeanMachine Job Script By Jimathy"
|
||||
fx_version 'cerulean'
|
||||
game "gta5"
|
||||
lua54 'yes'
|
||||
|
||||
server_scripts { 'server/*.lua' }
|
||||
shared_scripts { 'config.lua', 'locales/da.lua', 'shared/*.lua' }
|
||||
client_scripts { '@PolyZone/client.lua', '@PolyZone/BoxZone.lua', '@PolyZone/EntityZone.lua', '@PolyZone/CircleZone.lua', '@PolyZone/ComboZone.lua', 'client/*.lua', }
|
BIN
resources/[jims]/jim-beanmachine/image/beancoffee.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
resources/[jims]/jim-beanmachine/image/bigfruit.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
resources/[jims]/jim-beanmachine/image/bratte.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
resources/[jims]/jim-beanmachine/image/burger-milk.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
resources/[jims]/jim-beanmachine/image/caffeagra.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
resources/[jims]/jim-beanmachine/image/cheesecake.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
resources/[jims]/jim-beanmachine/image/chickenbreast.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
resources/[jims]/jim-beanmachine/image/chips.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
resources/[jims]/jim-beanmachine/image/chocolate.png
Normal file
After Width: | Height: | Size: 8.5 KiB |
BIN
resources/[jims]/jim-beanmachine/image/ecoffee.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
resources/[jims]/jim-beanmachine/image/ecola.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
resources/[jims]/jim-beanmachine/image/ecolalight.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
resources/[jims]/jim-beanmachine/image/flusher.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
resources/[jims]/jim-beanmachine/image/gunkaccino.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
resources/[jims]/jim-beanmachine/image/highnoon.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
resources/[jims]/jim-beanmachine/image/orange.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
resources/[jims]/jim-beanmachine/image/oyster.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
resources/[jims]/jim-beanmachine/image/popdonut.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
resources/[jims]/jim-beanmachine/image/rhinohorn.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
resources/[jims]/jim-beanmachine/image/speedball.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
resources/[jims]/jim-beanmachine/image/sprunk.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
resources/[jims]/jim-beanmachine/image/sprunklight.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
resources/[jims]/jim-beanmachine/image/sugar.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
resources/[jims]/jim-beanmachine/image/watermelon.png
Normal file
After Width: | Height: | Size: 18 KiB |
229
resources/[jims]/jim-beanmachine/install.md
Normal file
@ -0,0 +1,229 @@
|
||||
Thank you for your purchase <3 I hope you have fun with this script and that it brings jobs and RP to your server
|
||||
|
||||
If you need support I now have a discord available, it helps me keep track of issues and give better support.
|
||||
|
||||
https://discord.gg/xKgQZ6wZvS
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
# INSTALLATION
|
||||
|
||||
Check the `Config.lua` for the settings you need to change
|
||||
|
||||
To enable or disable a location, toggle `zoneEnable` in their Locations table
|
||||
|
||||
## Inventory Images
|
||||
Add the item images to your inventory script
|
||||
|
||||
`[qb]` > `qb-inventory` > `html` > `images`
|
||||
|
||||
## Items.lua
|
||||
|
||||
Under the QBShared.Items = {
|
||||
|
||||
--Jim-BeanMachine
|
||||
["beancoffee"] = {["name"] = "beancoffee", ["label"] = "Coffe Beans", ["weight"] = 100, ["type"] = "item", ["image"] = "beancoffee.png", ["unique"] = false, ["useable"] = false, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "", ['hunger'] = math.random(20, 30) },
|
||||
["beandonut"] = {["name"] = "beandonut", ["label"] = "Donut", ["weight"] = 100, ["type"] = "item", ["image"] = "popdonut.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "", ['hunger'] = math.random(20, 30) },
|
||||
["rhinohorn"] = {["name"] = "rhinohorn", ["label"] = "Rhino Horn", ["weight"] = 100, ["type"] = "item", ["image"] = "rhinohorn.png", ["unique"] = false, ["useable"] = false, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "" },
|
||||
["oystershell"] = {["name"] = "oystershell", ["label"] = "Oyster Shell", ["weight"] = 100, ["type"] = "item", ["image"] = "oyster.png", ["unique"] = false, ["useable"] = false, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "" },
|
||||
["watermelon"] = {["name"] = "watermelon", ["label"] = "WaterMelon Slice", ["weight"] = 100, ["type"] = "item", ["image"] = "watermelon.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "", ['hunger'] = math.random(20, 30), ['thirst'] = math.random(20, 30) },
|
||||
|
||||
["bigfruit"] = {["name"] = "bigfruit", ["label"] = "The Big Fruit", ["weight"] = 100, ["type"] = "item", ["image"] = "bigfruit.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "", ['thirst'] = math.random(20, 30) },
|
||||
["highnoon"] = {["name"] = "highnoon", ["label"] = "Highnoon", ["weight"] = 100, ["type"] = "item", ["image"] = "highnoon.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "", ['thirst'] = math.random(20, 30) },
|
||||
["speedball"] = {["name"] = "speedball", ["label"] = "The SpeedBall", ["weight"] = 100, ["type"] = "item", ["image"] = "speedball.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "", ['thirst'] = math.random(20, 30) },
|
||||
["gunkaccino"] = {["name"] = "gunkaccino", ["label"] = "The Gunkaccino", ["weight"] = 100, ["type"] = "item", ["image"] = "gunkaccino.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "", ['thirst'] = math.random(20, 30) },
|
||||
["bratte"] = {["name"] = "bratte", ["label"] = "The Bratte", ["weight"] = 100, ["type"] = "item", ["image"] = "bratte.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "", ['thirst'] = math.random(20, 30) },
|
||||
["flusher"] = {["name"] = "flusher", ["label"] = "The Flusher", ["weight"] = 100, ["type"] = "item", ["image"] = "flusher.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "", ['thirst'] = math.random(20, 30) },
|
||||
["ecocoffee"] = {["name"] = "ecocoffee", ["label"] = "The Eco-ffee", ["weight"] = 100, ["type"] = "item", ["image"] = "ecoffee.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "", ['thirst'] = math.random(20, 30) },
|
||||
["caffeagra"] = {["name"] = "caffeagra", ["label"] = "Caffeagra", ["weight"] = 100, ["type"] = "item", ["image"] = "caffeagra.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "", ['thirst'] = math.random(20, 30) },
|
||||
|
||||
["chocolate"] = {["name"] = "chocolate", ["label"] = "Chocolate", ["weight"] = 200, ["type"] = "item", ["image"] = "chocolate.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = false, ["combinable"] = nil, ["description"] = "Chocolate Bar", ['hunger'] = math.random(10, 20) },
|
||||
["cheesecake"] = {["name"] = "cheesecake", ["label"] = "Cheese Cake", ["weight"] = 100, ["type"] = "item", ["image"] = "cheesecake.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "", ['hunger'] = math.random(20, 30) },
|
||||
["crisps"] = {["name"] = "crisps", ["label"] = "Crisps", ["weight"] = 100, ["type"] = "item", ["image"] = "chips.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "", ['hunger'] = math.random(20, 30) },
|
||||
["sugar"] = {["name"] = "sugar", ["label"] = "Sugar", ["weight"] = 100, ["type"] = "item", ["image"] = "sugar.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = false, ["combinable"] = nil, ["description"] = "", ['hunger'] = math.random(10, 20) },
|
||||
["orange"] = {["name"] = "orange", ["label"] = "Orange", ["weight"] = 200, ["type"] = "item", ["image"] = "orange.png", ["unique"] = false, ["useable"] = false, ["shouldClose"] = false, ["combinable"] = nil, ["description"] = "An Orange." },
|
||||
["milk"] = {["name"] = "milk", ["label"] = "Milk", ["weight"] = 300, ["type"] = "item", ["image"] = "burger-milk.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "Carton of Milk", ['thirst'] = math.random(10, 20) },
|
||||
["chickenbreast"] = {["name"] = "chickenbreast", ["label"] = "Chicken Breast", ["weight"] = 100, ["type"] = "item", ["image"] = "chickenbreast.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = false, ["combinable"] = nil, ["description"] = "", ['hunger'] = math.random(10, 20) },
|
||||
|
||||
["sprunk"] = {["name"] = "sprunk", ["label"] = "Sprunk", ["weight"] = 100, ["type"] = "item", ["image"] = "sprunk.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "", ['thirst'] = math.random(20, 30) },
|
||||
["sprunklight"] = {["name"] = "sprunklight", ["label"] = "Sprunk Light", ["weight"] = 100, ["type"] = "item", ["image"] = "sprunklight.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "", ['thirst'] = math.random(20, 30) },
|
||||
["ecola"] = {["name"] = "ecola", ["label"] = "eCola", ["weight"] = 100, ["type"] = "item", ["image"] = "ecola.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "", ['thirst'] = math.random(20, 30) },
|
||||
["ecolalight"] = {["name"] = "ecolalight", ["label"] = "eCola Light", ["weight"] = 100, ["type"] = "item", ["image"] = "ecolalight.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "", ['thirst'] = math.random(20, 30) },
|
||||
|
||||
## Jobs
|
||||
Under the QBShared.Jobs = {
|
||||
|
||||
['beanmachine'] = {
|
||||
label = 'Bean Machine',
|
||||
defaultDuty = true,
|
||||
grades = {
|
||||
['0'] = { name = 'Recruit', payment = 50 },
|
||||
['1'] = { name = 'Novice', payment = 75 },
|
||||
['2'] = { name = 'Experienced', payment = 100 },
|
||||
['3'] = { name = 'Advanced', payment = 125 },
|
||||
['4'] = { name = 'Manager', isboss = true, payment = 150 },
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
## Payment Systems
|
||||
The payment system that is being used is my free script, jim-payments
|
||||
|
||||
This system supports receipts being handed out to wokers who are clocked in and working
|
||||
They can then trade this in at the bank for rewards
|
||||
|
||||
Grab it at: https://github.com/jimathy/jim-payments
|
||||
|
||||
# qb-management:
|
||||
|
||||
Update to the latest github version
|
||||
Make sure the job "beanmachine" has been added to the database
|
||||
The menu's targets should be accessible to bosses at clockin areas
|
||||
|
||||
## Emotes
|
||||
Custom emotes currently run through dpemotes, its the easier option and adds extra emotes for you to use :)
|
||||
|
||||
These go in your [standalone] > dpemotes > client > AnimationList.lua
|
||||
At about line 1666, place these under DP.PropEmotes = {
|
||||
|
||||
|
||||
["ecola"] = {"mp_player_intdrink", "loop_bottle", "E-cola", AnimationOptions =
|
||||
{ Prop = "prop_ecola_can", PropBone = 18905, PropPlacement = {0.12, 0.008, 0.03, 240.0, -60.0},
|
||||
EmoteMoving = true, EmoteLoop = true, }},
|
||||
["sprunk"] = {"mp_player_intdrink", "loop_bottle", "Sprunk", AnimationOptions =
|
||||
{ Prop = "v_res_tt_can03", PropBone = 18905, PropPlacement = {0.12, 0.008, 0.03, 240.0, -60.0},
|
||||
EmoteMoving = true, EmoteLoop = true, }},
|
||||
["crisps"] = {"amb@world_human_drinking@coffee@male@idle_a", "idle_c", "Crisps", AnimationOptions =
|
||||
{ Prop = 'v_ret_ml_chips2', PropBone = 28422, PropPlacement = {0.01, -0.05, -0.1, 0.0, 0.0, 90.0},
|
||||
EmoteLoop = true, EmoteMoving = true, }},
|
||||
["bmcoffee1"] = {"amb@world_human_drinking@coffee@male@idle_a", "idle_c", "Coffee2", AnimationOptions =
|
||||
{ Prop = 'prop_fib_coffee', PropBone = 28422, PropPlacement = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||
EmoteLoop = true, EmoteMoving = true, }},
|
||||
["bmcoffee2"] = {"amb@world_human_drinking@coffee@male@idle_a", "idle_c", "Coffee3", AnimationOptions =
|
||||
{ Prop = 'ng_proc_coffee_01a', PropBone = 28422, PropPlacement = {0.0, 0.0, -0.06, 0.0, 0.0, 0.0},
|
||||
EmoteLoop = true, EmoteMoving = true, }},
|
||||
["bmcoffee3"] = {"amb@world_human_drinking@coffee@male@idle_a", "idle_c", "Coffee3", AnimationOptions =
|
||||
{ Prop = 'v_club_vu_coffeecup', PropBone = 28422, PropPlacement = {0.0, 0.0, -0.06, 0.0, 0.0, 0.0},
|
||||
EmoteLoop = true, EmoteMoving = true, }},
|
||||
["milk"] = {"mp_player_intdrink", "loop_bottle", "Milk", AnimationOptions =
|
||||
{ Prop = "v_res_tt_milk", PropBone = 18905, PropPlacement = {0.10, 0.008, 0.07, 240.0, -60.0},
|
||||
EmoteMoving = true, EmoteLoop = true, }},
|
||||
["donut2"] = {"mp_player_inteat@burger", "mp_player_int_eat_burger", "Donut2", AnimationOptions =
|
||||
{ Prop = 'prop_donut_02', PropBone = 18905, PropPlacement = {0.13, 0.05, 0.02, -50.0, 100.0, 270.0},
|
||||
EmoteMoving = true, EmoteLoop = true, }},
|
||||
|
||||
--------------------------------------------------------------------------------------------------
|
||||
|
||||
## Jim-Consumables item setup - (Optional) - (https://github.com/jimathy/jim-consumables)
|
||||
- Support for new `Jim-Consumables` automated adding of items and emotes
|
||||
- Start `jim-consumables` BEFORE this script and set `Config.JimConsumables` to `true` for it to work
|
||||
- In Jim-Beanmachine's `config.lua` set `JimConsumables` to true
|
||||
- Restart/Ensure Jim-Beanmachine
|
||||
|
||||
- Restart Jim-Consumables
|
||||
|
||||
--------------------------------------------------------------------------------------------------
|
||||
|
||||
## Changelog
|
||||
|
||||
### v1.4.4:
|
||||
- Add "Multi-Craft" option in the config.lua
|
||||
- Split-Stack item exploit fix
|
||||
- Optional: Support for new `Jim-Consumables` automated item adding events
|
||||
- (Start `jim-consumables` BEFORE this script and set `Config.JimConsumables` to `true` for it to work)
|
||||
- (https://github.com/jimathy/jim-consumables)
|
||||
- Change/Add support for creating jobGarages in (https://github.com/jimathy/jim-jobgarage)
|
||||
|
||||
### v1.4.3
|
||||
- Added image icons to ox_lib menus
|
||||
- Added Version Update check
|
||||
|
||||
### v1.4.2
|
||||
- Improved `OX_Lib` Context support (better layout for ingredients)
|
||||
- Improved `OX_Inv` support
|
||||
- Added `OX_Lib` Progressbar suppport
|
||||
- *Basic* `OX_Lib` notification support (Set `Config.Notify = "ox"`)
|
||||
- Improved script stopping/restarting events
|
||||
- Added more options to blip creation
|
||||
- Locale fixes
|
||||
- Updated shared functions to give more info and be more optimized
|
||||
- Merged built-in eating events into one optimized event
|
||||
- Fix emote references for jim-consumables and built in events ("bmcoffee1" not "bmcoffee")
|
||||
|
||||
### v1.4.1
|
||||
- Add support for OX Lib's Context menu
|
||||
- Updated emote code in built-in consumable events
|
||||
|
||||
### v1.4
|
||||
- Support for changing Core name
|
||||
- Support added for OX_Target
|
||||
- Support added for OX_Inventory
|
||||
- Added autoClock variable to locations config
|
||||
- This helps define if leaving or entering the zone clocks in or out
|
||||
|
||||
### v1.3.4
|
||||
- Updated install.md
|
||||
- Included instructions to make use of Jim-Consuambles if wanted
|
||||
- Add de.lua locale
|
||||
- Updated built-in client and server Hasitem events to be more accurate
|
||||
- Support for different job roles at each location
|
||||
- Fix for built in job garages letting anyone grab a vehicle
|
||||
|
||||
### v1.3.3
|
||||
- Locale support thanks to Dafke
|
||||
|
||||
### v1.3.2
|
||||
- Workaround for the `HasItem()` allowing crafting when items aren't there
|
||||
|
||||
### v1.3.1
|
||||
- Made the `HasItem` functions built in, so no edits to core needed
|
||||
- This allows optimizations + makes crafting menus open/load much faster
|
||||
- Add item duping protection to item crafting
|
||||
|
||||
### v1.3
|
||||
- New Location supported, the free MLO - https://www.gta5-mods.com/maps/mlo-bean-machine-fivem-sp
|
||||
- Rewrote the locations and how they are handled in the client to allow easier additions of new locations
|
||||
- Rewrote the chair code to be more optimzed and handle multiple locations better
|
||||
- Rewrote the garage.lua to support new functions
|
||||
- Added shared function file to optimize code and improve loading of props and blips
|
||||
- Made use of new custom lookEnt() event to make player look towards points of interactions.
|
||||
|
||||
### v1.2.1
|
||||
- Added support ps-progressbar
|
||||
|
||||
### v1.2
|
||||
- Added Support for Crafting CheckMarks
|
||||
- This is a toggle in the config, if it causes issues(like lag) disable it
|
||||
- Added Support for Jim-Shops
|
||||
- Added Support for new qb-menu icons
|
||||
- Added Job Garages for deliveries to both default locations
|
||||
- QoL fixes
|
||||
- Improved and optimized loading of targets and props
|
||||
- UncleJust changes
|
||||
- Slushie machine prop now added to separate the Soda's and Slushie targets
|
||||
- Added Prepared Food Stash to the fridge
|
||||
- Gabz Changes
|
||||
- Added Prepared Food Stash to the Donut Counter
|
||||
- Upgraded Crafting systems to be more optimised
|
||||
- Changed "Donut" menu to be a shop instead of just grabbing them
|
||||
- Added simple support for Toys/Prizes
|
||||
- BossMenu is now accessible from the same areas as clock in targets
|
||||
|
||||
### v1.1.1
|
||||
- Fixed typo breaking coffee menu
|
||||
- Fixed type making "crisps" unusable
|
||||
|
||||
### v1.1
|
||||
- Fix for item check callback
|
||||
- Added support for grabbing images from inventory script
|
||||
- You need to set your inventory image folder link in the config if not using qb-inventory
|
||||
|
||||
### v1.0.2
|
||||
- Added config option for zones
|
||||
- zoneEable, enables or disables the chosen zone and its map blip
|
||||
- Added Debug messages to server.lua
|
||||
- helps..debug..any issues with the script
|
||||
- Missed chocolate completely from the list
|
||||
- Even the item check in client.lua was missing it.
|
||||
- Added more Custom Emotes
|
||||
- Didn't know there were acutal extra BM Coffee Props
|
56
resources/[jims]/jim-beanmachine/locales/da.lua
Normal file
@ -0,0 +1,56 @@
|
||||
Loc["da"] = {
|
||||
error = {
|
||||
["someone_already_sitting"] = "Der sidder allerede nogen..",
|
||||
["not_clocked_in"] = "Du er ikke på arbejde!",
|
||||
["cancelled"] = "Afbrudt",
|
||||
["in_the_way"] = " er i vejen",
|
||||
},
|
||||
success = {
|
||||
["success_washed_hands"] = "Du vaskede hænder!",
|
||||
["retrieved"] = "Hentede ",
|
||||
["job_vehicle_map"] = "Firmabil markeret på kortet",
|
||||
},
|
||||
info = {
|
||||
|
||||
},
|
||||
targetinfo = {
|
||||
["sit_down"] = "Sid ned",
|
||||
["wash_hands"] = "Vask dine hænder",
|
||||
["open_counter"] = "Åben",
|
||||
["charge_customer"] = "Opkræv kunde",
|
||||
["open_storage"] = "Åben Lager",
|
||||
["prepare_coffee"] = "Lav Kaffe",
|
||||
["prepare_slush"] = "Lav Slush",
|
||||
["grab_soda"] = "Tag Sodavand",
|
||||
["grab_food"] = "Tag Mad",
|
||||
["open_stash"] = "Åben Stash",
|
||||
["toggle_duty"] = "Skift Vagt",
|
||||
["open_bossmenu"] = "Åben Bossmenu",
|
||||
["open_shop"] = "Åben Butik",
|
||||
},
|
||||
email = {
|
||||
|
||||
},
|
||||
menu = {
|
||||
["close"] = "Luk",
|
||||
["back"] = "Tilbage",
|
||||
["slush_menu"] = "Slush Menu",
|
||||
["drink_menu"] = "Drinks Menu",
|
||||
["job_vehicles"] = "Firmabiler",
|
||||
["job_garage"] = "Firmagarage",
|
||||
["vehicle"] = "Køretøj: ",
|
||||
["plate"] = "<br> Nummerplade: [",
|
||||
["remove_vehicle"] = "Fjern køretøj",
|
||||
["vehicle_out_of_garage"] = "Køretøj ude af garage",
|
||||
},
|
||||
commands = {
|
||||
|
||||
},
|
||||
progressbar = {
|
||||
["washing_hands"] = 'Vasker hænder',
|
||||
["making"] = "Laver ",
|
||||
["drinking"] = "Drikker ",
|
||||
["eating"] = "Spiser ",
|
||||
},
|
||||
warning = {},
|
||||
}
|
161
resources/[jims]/jim-beanmachine/server/server.lua
Normal file
@ -0,0 +1,161 @@
|
||||
local QBCore = exports[Config.Core]:GetCoreObject()
|
||||
|
||||
AddEventHandler('onResourceStart', function(r) if GetCurrentResourceName() ~= r then return end
|
||||
for k, v in pairs(Crafting) do for i = 1, #v do
|
||||
for l, b in pairs(v[i]) do if not QBCore.Shared.Items[l] then print("Crafting: Missing Item from QBCore.Shared.Items: '"..l.."'") end
|
||||
for j, c in pairs(b) do if not QBCore.Shared.Items[j] then print("Crafting: Missing Item from QBCore.Shared.Items: '"..j.."'") end end end end end
|
||||
for i = 1, #Config.FoodItems.items do
|
||||
if not QBCore.Shared.Items[Config.FoodItems.items[i].name] then print("Store: Missing Item from QBCore.Shared.Items: '"..Config.FoodItems.items[i].name.."'") end
|
||||
end
|
||||
for i = 1, #Config.DesertItems.items do
|
||||
if not QBCore.Shared.Items[Config.DesertItems.items[i].name] then print("Store: Missing Item from QBCore.Shared.Items: '"..Config.DesertItems.items[i].name.."'") end
|
||||
end
|
||||
for i = 1, #Config.SodaItems.items do
|
||||
if not QBCore.Shared.Items[Config.SodaItems.items[i].name] then print("Store: Missing Item from QBCore.Shared.Items: '"..Config.SodaItems.items[i].name.."'") end
|
||||
end
|
||||
for k, v in pairs(Config.Locations) do
|
||||
if not QBCore.Shared.Jobs[v.job] then print("Error: Job role not found - '"..v.job.."'") end
|
||||
if v.garage then
|
||||
TriggerEvent("jim-jobgarage:server:syncAddLocations", { job = v.job, garage = v.garage }) -- Job Garage creation
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
if not Config.JimConsumables then
|
||||
CreateThread(function()
|
||||
local drinks = { "bigfruit", "highnoon", "speedball", "gunkaccino", "bratte", "flusher", "ecocoffee", "caffeagra", "ecola", "ecolalight", "sprunk", "sprunklight" }
|
||||
for k,v in pairs(drinks) do QBCore.Functions.CreateUseableItem(v, function(source, item) TriggerClientEvent('jim-beanmachine:client:Consume', source, item.name, "drink") end) end
|
||||
|
||||
local food = { "cheesecake", "watermelon", "beandonut", "chocolate", "crisps", }
|
||||
for k,v in pairs(food) do QBCore.Functions.CreateUseableItem(v, function(source, item) TriggerClientEvent('jim-beanmachine:client:Consume', source, item.name, "food") end) end
|
||||
end)
|
||||
else
|
||||
local foodTable = {
|
||||
["bigfruit"] = { emote = "bmcoffee1", canRun = false, time = math.random(5000, 6000), stress = math.random(2, 4), heal = 0, armor = 0, type = "drink", stats = { thirst = math.random(20, 30), }},
|
||||
["highnoon"] = { emote = "bmcoffee1", canRun = false, time = math.random(5000, 6000), stress = math.random(2, 4), heal = 0, armor = 0, type = "drink", stats = { thirst = math.random(20, 30), }},
|
||||
["speedball"] = { emote = "bmcoffee1", canRun = false, time = math.random(5000, 6000), stress = math.random(2, 4), heal = 0, armor = 0, type = "drink", stats = { thirst = math.random(20, 30), }},
|
||||
["gunkaccino"] = { emote = "bmcoffee1", canRun = false, time = math.random(5000, 6000), stress = math.random(2, 4), heal = 0, armor = 0, type = "drink", stats = { thirst = math.random(20, 30), }},
|
||||
["bratte"] = { emote = "bmcoffee1", canRun = false, time = math.random(5000, 6000), stress = math.random(2, 4), heal = 0, armor = 0, type = "drink", stats = { thirst = math.random(20, 30), }},
|
||||
["flusher"] = { emote = "bmcoffee2", canRun = false, time = math.random(5000, 6000), stress = math.random(2, 4), heal = 0, armor = 0, type = "drink", stats = { thirst = math.random(20, 30), }},
|
||||
["ecocoffee"] = { emote = "bmcoffee", canRun = false, time = math.random(5000, 6000), stress = math.random(2, 4), heal = 0, armor = 0, type = "drink", stats = { thirst = math.random(20, 30), }},
|
||||
["caffeagra"] = { emote = "bmcoffee3", canRun = false, time = math.random(5000, 6000), stress = math.random(2, 4), heal = 0, armor = 0, type = "drink", stats = { thirst = math.random(20, 30), }},
|
||||
["cheesecake"] = { emote = "sandwich", canRun = false, time = math.random(5000, 6000), stress = math.random(2, 4), heal = 0, armor = 0, type = "food", stats = { hunger = math.random(20, 30), }},
|
||||
["watermelon"] = { emote = "sandwich", canRun = false, time = math.random(5000, 6000), stress = math.random(2, 4), heal = 0, armor = 0, type = "food", stats = { hunger = math.random(20, 30), thirst = math.random(20, 30) }},
|
||||
["beandonut"] = { emote = "donut2", canRun = false, time = math.random(5000, 6000), stress = math.random(2, 4), heal = 0, armor = 0, type = "food", stats = { hunger = math.random(20, 30), }},
|
||||
["chocolate"] = { emote = "egobar", canRun = false, time = math.random(5000, 6000), stress = math.random(2, 4), heal = 0, armor = 0, type = "food", stats = { hunger = math.random(10, 20), }},
|
||||
["crisps"] = { emote = "crisps", canRun = false, time = math.random(5000, 6000), stress = math.random(2, 4), heal = 0, armor = 0, type = "food", stats = { hunger = math.random(20, 30), }},
|
||||
["ecola"] = { emote = "ecola", canRun = false, time = math.random(5000, 6000), stress = math.random(2, 4), heal = 0, armor = 0, type = "drink", stats = { thirst = math.random(20,30), }},
|
||||
["ecolalight"] = { emote = "ecola", canRun = false, time = math.random(5000, 6000), stress = math.random(2, 4), heal = 0, armor = 0, type = "drink", stats = { thirst = math.random(20,30), }},
|
||||
["sprunk"] = { emote = "sprunk", canRun = false, time = math.random(5000, 6000), stress = math.random(2, 4), heal = 0, armor = 0, type = "drink", stats = { thirst = math.random(20,30), }},
|
||||
["sprunklight"] = { emote = "sprunk", canRun = false, time = math.random(5000, 6000), stress = math.random(2, 4), heal = 0, armor = 0, type = "drink", stats = { thirst = math.random(20,30), }},
|
||||
}
|
||||
local emoteTable = {
|
||||
["ecola"] = {"mp_player_intdrink", "loop_bottle", "E-cola", AnimationOptions = { Prop = "prop_ecola_can", PropBone = 18905, PropPlacement = {0.12, 0.008, 0.03, 240.0, -60.0}, EmoteMoving = true, EmoteLoop = true, }},
|
||||
["sprunk"] = {"mp_player_intdrink", "loop_bottle", "Sprunk", AnimationOptions = { Prop = "v_res_tt_can03", PropBone = 18905, PropPlacement = {0.12, 0.008, 0.03, 240.0, -60.0}, EmoteMoving = true, EmoteLoop = true, }},
|
||||
["crisps"] = {"amb@world_human_drinking@coffee@male@idle_a", "idle_c", "Crisps", AnimationOptions = { Prop = 'v_ret_ml_chips2', PropBone = 28422, PropPlacement = {0.01, -0.05, -0.1, 0.0, 0.0, 90.0}, EmoteLoop = true, EmoteMoving = true, }},
|
||||
["bmcoffee1"] = {"amb@world_human_drinking@coffee@male@idle_a", "idle_c", "Coffee2", AnimationOptions = { Prop = 'prop_fib_coffee', PropBone = 28422, PropPlacement = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, EmoteLoop = true, EmoteMoving = true, }},
|
||||
["bmcoffee2"] = {"amb@world_human_drinking@coffee@male@idle_a", "idle_c", "Coffee3", AnimationOptions = { Prop = 'ng_proc_coffee_01a', PropBone = 28422, PropPlacement = {0.0, 0.0, -0.06, 0.0, 0.0, 0.0}, EmoteLoop = true, EmoteMoving = true, }},
|
||||
["bmcoffee3"] = {"amb@world_human_drinking@coffee@male@idle_a", "idle_c", "Coffee3", AnimationOptions = { Prop = 'v_club_vu_coffeecup', PropBone = 28422, PropPlacement = {0.0, 0.0, -0.06, 0.0, 0.0, 0.0}, EmoteLoop = true, EmoteMoving = true, }},
|
||||
["milk"] = {"mp_player_intdrink", "loop_bottle", "Milk", AnimationOptions = { Prop = "v_res_tt_milk", PropBone = 18905, PropPlacement = {0.10, 0.008, 0.07, 240.0, -60.0}, EmoteMoving = true, EmoteLoop = true, }},
|
||||
["donut2"] = {"mp_player_inteat@burger", "mp_player_int_eat_burger", "Donut2", AnimationOptions = { Prop = 'prop_donut_02', PropBone = 18905, PropPlacement = {0.13, 0.05, 0.02, -50.0, 100.0, 270.0}, EmoteMoving = true, EmoteLoop = true, }},
|
||||
["ecola"] = {"mp_player_intdrink", "loop_bottle", "e-cola", AnimationOptions = { Prop = "prop_ecola_can", PropBone = 18905, PropPlacement = {0.12, 0.008, 0.03, 240.0, -60.0}, EmoteMoving = true, EmoteLoop = true, }},
|
||||
["sprunk"] = {"mp_player_intdrink", "loop_bottle", "sprunk", AnimationOptions = { Prop = "v_res_tt_can03", PropBone = 18905, PropPlacement = {0.12, 0.008, 0.03, 240.0, -60.0}, EmoteMoving = true, EmoteLoop = true, }},
|
||||
}
|
||||
for k, v in pairs(foodTable) do TriggerEvent("jim-consumables:server:syncAddItem", k, v) end
|
||||
for k, v in pairs(emoteTable) do TriggerEvent("jim-consumables:server:syncAddEmote", k, v) end
|
||||
end
|
||||
|
||||
---Crafting
|
||||
RegisterServerEvent('jim-beanmachine:Crafting:GetItem', function(ItemMake, craftable)
|
||||
local src = source
|
||||
local Player = QBCore.Functions.GetPlayer(src)
|
||||
--This grabs the table from client and removes the item requirements
|
||||
local amount = craftable["amount"] or 1
|
||||
if craftable then
|
||||
--if craftable["amount"] then amount = craftable["amount"] end
|
||||
for k, v in pairs(craftable[ItemMake]) do TriggerEvent("jim-beanmachine:server:toggleItem", false, tostring(k), v, src) end
|
||||
end
|
||||
--This should give the item, while the rest removes the requirements
|
||||
TriggerEvent("jim-beanmachine:server:toggleItem", true, ItemMake, amount, src)
|
||||
end)
|
||||
|
||||
local function dupeWarn(src, item)
|
||||
local P = QBCore.Functions.GetPlayer(src)
|
||||
print("^5DupeWarn: ^1"..P.PlayerData.charinfo.firstname.." "..P.PlayerData.charinfo.lastname.."^7(^1"..tostring(src).."^7) ^2Tried to remove item ^7('^3"..item.."^7')^2 but it wasn't there^7")
|
||||
-- if not Config.Debug then DropPlayer(src, "^1Kicked for attempting to duplicate items") end
|
||||
print("^5DupeWarn: ^1"..P.PlayerData.charinfo.firstname.." "..P.PlayerData.charinfo.lastname.."^7(^1"..tostring(src).."^7) ^2Dropped from server for item duplicating^7")
|
||||
end
|
||||
|
||||
RegisterNetEvent('jim-beanmachine:server:toggleItem', function(give, item, amount, newsrc)
|
||||
local src = newsrc or source
|
||||
local Player = QBCore.Functions.GetPlayer(src)
|
||||
local remamount = (amount or 1)
|
||||
if give == 0 or give == false then
|
||||
if HasItem(src, item, amount or 1) then -- check if you still have the item
|
||||
while remamount > 0 do if Player.Functions.RemoveItem(item, 1) then end remamount -= 1 end
|
||||
TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items[item], "remove", amount or 1)
|
||||
if Config.Debug then print("^5Debug^7: ^1Removing ^2from Player^7(^2"..src.."^7) '^6"..QBCore.Shared.Items[item].label.."^7(^2x^6"..(amount or "1").."^7)'") end
|
||||
else dupeWarn(src, item) end -- if not boot the player
|
||||
else
|
||||
if Player.Functions.AddItem(item, amount or 1) then
|
||||
TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items[item], "add", amount or 1)
|
||||
if Config.Debug then print("^5Debug^7: ^4Giving ^2Player^7(^2"..src.."^7) '^6"..QBCore.Shared.Items[item].label.."^7(^2x^6"..(amount or "1").."^7)'") end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
if Config.Inv == "ox" then
|
||||
--Unclejust--
|
||||
exports.ox_inventory:RegisterStash("beanmachine_UCounter", "Beanmachine Counter", 20, 400000)
|
||||
exports.ox_inventory:RegisterStash("beanmachine_UStash", "Beanmachine Stash", 20, 400000)
|
||||
exports.ox_inventory:RegisterShop("UBeanFridge", { name = Config.FoodItems.label, inventory = Config.FoodItems.items })
|
||||
exports.ox_inventory:RegisterShop("UBeanSoda", { name = Config.SodaItems.label, inventory = Config.SodaItems.items })
|
||||
exports.ox_inventory:RegisterShop("UBeanDonut", { name = Config.DesertItems.label, inventory = Config.DesertItems.items })
|
||||
--Gabz--
|
||||
exports.ox_inventory:RegisterStash("beanmachine_Counter", "Beanmachine Counter", 20, 400000)
|
||||
exports.ox_inventory:RegisterStash("beanmachine_Counter2", "Beanmachine Counter 2", 20, 400000)
|
||||
exports.ox_inventory:RegisterStash("beanmachine_LegionStash", "Beanmachine Legion Stash", 20, 400000)
|
||||
exports.ox_inventory:RegisterShop("BeanFridge", { name = Config.FoodItems.label, inventory = Config.FoodItems.items})
|
||||
exports.ox_inventory:RegisterShop("BeanFridge2", { name = Config.FoodItems.label, inventory = Config.FoodItems.items})
|
||||
exports.ox_inventory:RegisterShop("BeanSoda", { name = Config.SodaItems.label, inventory = Config.SodaItems.items})
|
||||
exports.ox_inventory:RegisterShop("BeanDonut", { name = Config.DesertItems.label, inventory = Config.DesertItems.items})
|
||||
--flx--
|
||||
exports.ox_inventory:RegisterStash("beanmachine_flxCounter", "Beanmachine Counter", 20, 400000)
|
||||
exports.ox_inventory:RegisterStash("beanmachine_flxStash", "Beanmachine Stash", 20, 400000)
|
||||
exports.ox_inventory:RegisterShop("flxBeanFridge", { name = Config.FoodItems.label, inventory = Config.FoodItems.items })
|
||||
exports.ox_inventory:RegisterShop("flxBeanSoda", { name = Config.SodaItems.label, inventory = Config.SodaItems.items })
|
||||
exports.ox_inventory:RegisterShop("flxBeanDonut", { name = Config.DesertItems.label, inventory = Config.DesertItems.items })
|
||||
function HasItem(src, items, amount)
|
||||
local count = exports.ox_inventory:Search(src, 'count', items)
|
||||
if exports.ox_inventory:Search(src, 'count', items) >= (amount or 1) then if Config.Debug then print("^5Debug^7: ^3HasItem^7: ^5FOUND^7 x^3"..count.."^7 ^3"..tostring(items)) end return true
|
||||
else if Config.Debug then print("^5Debug^7: ^3HasItem^7: ^2Items ^1NOT FOUND^7") end return false end
|
||||
end
|
||||
else
|
||||
function HasItem(source, items, amount)
|
||||
local amount, count = amount or 1, 0
|
||||
local Player = QBCore.Functions.GetPlayer(source)
|
||||
if Config.Debug then print("^5Debug^7: ^3HasItem^7: ^2Checking if player has required item^7 '^3"..tostring(items).."^7'") end
|
||||
for _, itemData in pairs(Player.PlayerData.items) do
|
||||
if itemData and (itemData.name == items) then
|
||||
if Config.Debug then print("^5Debug^7: ^3HasItem^7: ^2Item^7: '^3"..tostring(items).."^7' ^2Slot^7: ^3"..itemData.slot.." ^7x(^3"..tostring(itemData.amount).."^7)") end
|
||||
count += itemData.amount
|
||||
end
|
||||
end
|
||||
if count >= amount then if Config.Debug then print("^5Debug^7: ^3HasItem^7: ^2Items ^5FOUND^7 x^3"..count.."^7") end return true end
|
||||
if Config.Debug then print("^5Debug^7: ^3HasItem^7: ^2Items ^1NOT FOUND^7") end return false
|
||||
end
|
||||
end
|
||||
|
||||
local function CheckVersion()
|
||||
PerformHttpRequest('https://raw.githubusercontent.com/jimathy/UpdateVersions/master/jim-beanmachine.txt', function(err, newestVersion, headers)
|
||||
local currentVersion = GetResourceMetadata(GetCurrentResourceName(), 'version')
|
||||
if not newestVersion then print("Currently unable to run a version check.") return end
|
||||
local advice = "^1You are currently running an outdated version^7, ^1please update^7"
|
||||
if newestVersion:gsub("%s+", "") == currentVersion:gsub("%s+", "") then advice = '^6You are running the latest version.^7'
|
||||
else
|
||||
-- print("^3Version Check^7: ^2Current^7: "..currentVersion.." ^2Latest^7: "..newestVersion)
|
||||
end
|
||||
-- print(advice)
|
||||
end)
|
||||
end
|
||||
CheckVersion()
|
391
resources/[jims]/jim-beanmachine/shared/shared.lua
Normal file
@ -0,0 +1,391 @@
|
||||
local QBCore = exports['qb-core']:GetCoreObject()
|
||||
RegisterNetEvent('QBCore:Client:UpdateObject', function() QBCore = exports['qb-core']:GetCoreObject() end)
|
||||
|
||||
local time = 1000
|
||||
function loadModel(model) if not HasModelLoaded(model) then
|
||||
if Config.Debug then print("^5Debug^7: ^2Loading Model^7: '^6"..model.."^7'") end
|
||||
while not HasModelLoaded(model) do
|
||||
if time > 0 then time -= 1 RequestModel(model)
|
||||
else time = 1000 print("^5Debug^7: ^3LoadModel^7: ^2Timed out loading model ^7'^6"..model.."^7'") break
|
||||
end
|
||||
Wait(10)
|
||||
end
|
||||
end end
|
||||
function unloadModel(model) if Config.Debug then print("^5Debug^7: ^2Removing Model^7: '^6"..model.."^7'") end SetModelAsNoLongerNeeded(model) end
|
||||
function loadAnimDict(dict) if not HasAnimDictLoaded(dict) then if Config.Debug then print("^5Debug^7: ^2Loading Anim Dictionary^7: '^6"..dict.."^7'") end while not HasAnimDictLoaded(dict) do RequestAnimDict(dict) Wait(5) end end end
|
||||
function unloadAnimDict(dict) if Config.Debug then print("^5Debug^7: ^2Removing Anim Dictionary^7: '^6"..dict.."^7'") end RemoveAnimDict(dict) end
|
||||
function loadPtfxDict(dict) if not HasNamedPtfxAssetLoaded(dict) then if Config.Debug then print("^5Debug^7: ^2Loading Ptfx Dictionary^7: '^6"..dict.."^7'") end while not HasNamedPtfxAssetLoaded(dict) do RequestNamedPtfxAsset(dict) Wait(5) end end end
|
||||
function unloadPtfxDict(dict) if Config.Debug then print("^5Debug^7: ^2Removing Ptfx Dictionary^7: '^6"..dict.."^7'") end RemoveNamedPtfxAsset(dict) end
|
||||
|
||||
function destroyProp(entity)
|
||||
if Config.Debug then print("^5Debug^7: ^2Destroying Prop^7: '^6"..entity.."^7'") end
|
||||
SetEntityAsMissionEntity(entity) Wait(5)
|
||||
--DetachEntity(entity, true, true) Wait(5)
|
||||
DeleteObject(entity)
|
||||
end
|
||||
|
||||
function makeProp(data, freeze, synced)
|
||||
loadModel(data.prop)
|
||||
local prop = CreateObject(data.prop, 0.0, 0.0, 0.0, synced or false, synced or false, false)
|
||||
SetEntityHeading(prop, data.coords.w+180.0)
|
||||
--FreezeEntityPosition(prop, freeze or false)
|
||||
SetEntityCompletelyDisableCollision(prop, true, false)
|
||||
DisableCamCollisionForEntity(prop)
|
||||
DisableCamCollisionForObject(prop)
|
||||
if Config.Debug then print("^5Debug^7: ^6Prop ^2Created ^7: '^6"..prop.."^7'") end
|
||||
return prop
|
||||
end
|
||||
function triggerNotify(title, message, type, src)
|
||||
if Config.Notify == "okok" then
|
||||
if not src then exports['okokNotify']:Alert(title, message, 6000, type)
|
||||
else TriggerClientEvent('okokNotify:Alert', src, title, message, 6000, type) end
|
||||
elseif Config.Notify == "qb" then
|
||||
if not src then TriggerEvent("QBCore:Notify", message, type)
|
||||
else TriggerClientEvent("QBCore:Notify", src, message, type) end
|
||||
elseif Config.Notify == "t" then
|
||||
if not src then exports['t-notify']:Custom({title = title, style = type, message = message, sound = true})
|
||||
else TriggerClientEvent('t-notify:client:Custom', src, { style = type, duration = 6000, title = title, message = message, sound = true, custom = true}) end
|
||||
elseif Config.Notify == "infinity" then
|
||||
if not src then TriggerEvent('infinity-notify:sendNotify', message, type)
|
||||
else TriggerClientEvent('infinity-notify:sendNotify', src, message, type) end
|
||||
elseif Config.Notify == "rr" then
|
||||
if not src then exports.rr_uilib:Notify({msg = message, type = type, style = "dark", duration = 6000, position = "top-right", })
|
||||
else TriggerClientEvent("rr_uilib:Notify", src, {msg = message, type = type, style = "dark", duration = 6000, position = "top-right", }) end
|
||||
end
|
||||
end
|
||||
|
||||
function countTable(table) local i = 0 for keys in pairs(table) do i += 1 end return i end
|
||||
|
||||
function toggleItem(give, item, amount) TriggerServerEvent("ns-bars:server:toggleItem", give, item, amount) end
|
||||
|
||||
--Screen Effects
|
||||
local alienEffect = false
|
||||
function AlienEffect()
|
||||
if alienEffect then return else alienEffect = true end
|
||||
if Config.Debug then print("^5Debug^7: ^3AlienEffect^7() ^2activated") end
|
||||
AnimpostfxPlay("DrugsMichaelAliensFightIn", 3.0, 0)
|
||||
Wait(math.random(5000, 8000))
|
||||
local Ped = PlayerPedId()
|
||||
local animDict = "MOVE_M@DRUNK@VERYDRUNK"
|
||||
loadAnimDict(animDict)
|
||||
SetPedCanRagdoll(Ped, true)
|
||||
ShakeGameplayCam('DRUNK_SHAKE', 2.80)
|
||||
SetTimecycleModifier("Drunk")
|
||||
SetPedMovementClipset(Ped, animDict, 1)
|
||||
SetPedMotionBlur(Ped, true)
|
||||
SetPedIsDrunk(Ped, true)
|
||||
Wait(1500)
|
||||
SetPedToRagdoll(Ped, 5000, 1000, 1, 0, 0, 0)
|
||||
Wait(13500)
|
||||
SetPedToRagdoll(Ped, 5000, 1000, 1, 0, 0, 0)
|
||||
Wait(120500)
|
||||
ClearTimecycleModifier()
|
||||
ResetScenarioTypesEnabled()
|
||||
ResetPedMovementClipset(Ped, 0)
|
||||
SetPedIsDrunk(Ped, false)
|
||||
SetPedMotionBlur(Ped, false)
|
||||
AnimpostfxStopAll()
|
||||
ShakeGameplayCam('DRUNK_SHAKE', 0.0)
|
||||
AnimpostfxPlay("DrugsMichaelAliensFight", 3.0, 0)
|
||||
Wait(math.random(45000, 60000))
|
||||
AnimpostfxPlay("DrugsMichaelAliensFightOut", 3.0, 0)
|
||||
AnimpostfxStop("DrugsMichaelAliensFightIn")
|
||||
AnimpostfxStop("DrugsMichaelAliensFight")
|
||||
AnimpostfxStop("DrugsMichaelAliensFightOut")
|
||||
alienEffect = false
|
||||
if Config.Debug then print("^5Debug^7: ^3AlienEffect^7() ^2stopped") end
|
||||
end
|
||||
local weedEffect = false
|
||||
function WeedEffect()
|
||||
if weedEffect then return else weedEffect = true end
|
||||
if Config.Debug then print("^5Debug^7: ^3WeedEffect^7() ^2activated") end
|
||||
AnimpostfxPlay("DrugsMichaelAliensFightIn", 3.0, 0)
|
||||
Wait(math.random(3000, 20000))
|
||||
AnimpostfxPlay("DrugsMichaelAliensFight", 3.0, 0)
|
||||
Wait(math.random(15000, 20000))
|
||||
AnimpostfxPlay("DrugsMichaelAliensFightOut", 3.0, 0)
|
||||
AnimpostfxStop("DrugsMichaelAliensFightIn")
|
||||
AnimpostfxStop("DrugsMichaelAliensFight")
|
||||
AnimpostfxStop("DrugsMichaelAliensFightOut")
|
||||
weedEffect = false
|
||||
if Config.Debug then print("^5Debug^7: ^3WeedEffect^7() ^2stopped") end
|
||||
end
|
||||
local trevorEffect = false
|
||||
function TrevorEffect()
|
||||
if trevorEffect then return else trevorEffect = true end
|
||||
if Config.Debug then print("^5Debug^7: ^3TrevorEffect^7() ^2activated") end
|
||||
AnimpostfxPlay("DrugsTrevorClownsFightIn", 3.0, 0)
|
||||
Wait(3000)
|
||||
AnimpostfxPlay("DrugsTrevorClownsFight", 3.0, 0)
|
||||
Wait(30000)
|
||||
AnimpostfxPlay("DrugsTrevorClownsFightOut", 3.0, 0)
|
||||
AnimpostfxStop("DrugsTrevorClownsFight")
|
||||
AnimpostfxStop("DrugsTrevorClownsFightIn")
|
||||
AnimpostfxStop("DrugsTrevorClownsFightOut")
|
||||
trevorEffect = false
|
||||
if Config.Debug then print("^5Debug^7: ^3TrevorEffect^7() ^2stopped") end
|
||||
end
|
||||
local turboEffect = false
|
||||
function TurboEffect()
|
||||
if turboEffect then return else turboEffect = true end
|
||||
if Config.Debug then print("^5Debug^7: ^3TurboEffect^7() ^2activated") end
|
||||
AnimpostfxPlay('RaceTurbo', 0, true)
|
||||
SetTimecycleModifier('rply_motionblur')
|
||||
ShakeGameplayCam('SKY_DIVING_SHAKE', 0.25)
|
||||
Wait(30000)
|
||||
StopGameplayCamShaking(true)
|
||||
SetTransitionTimecycleModifier('default', 0.35)
|
||||
Wait(1000)
|
||||
ClearTimecycleModifier()
|
||||
AnimpostfxStop('RaceTurbo')
|
||||
turboEffect = false
|
||||
if Config.Debug then print("^5Debug^7: ^3TurboEffect^7() ^2stopped") end
|
||||
end
|
||||
local rampageEffect = false
|
||||
function RampageEffect()
|
||||
if rampageEffect then return else rampageEffect = true end
|
||||
if Config.Debug then print("^5Debug^7: ^3RampageEffect^7() ^2activated") end
|
||||
AnimpostfxPlay('Rampage', 0, true)
|
||||
SetTimecycleModifier('rply_motionblur')
|
||||
ShakeGameplayCam('SKY_DIVING_SHAKE', 0.25)
|
||||
Wait(30000)
|
||||
StopGameplayCamShaking(true)
|
||||
SetTransitionTimecycleModifier('default', 0.35)
|
||||
Wait(1000)
|
||||
ClearTimecycleModifier()
|
||||
AnimpostfxStop('Rampage')
|
||||
rampageEffect = false
|
||||
if Config.Debug then print("^5Debug^7: ^3RampageEffect^7() ^2stopped") end
|
||||
end
|
||||
local focusEffect = false
|
||||
function FocusEffect()
|
||||
if focusEffect then return else focusEffect = true end
|
||||
if Config.Debug then print("^5Debug^7: ^3FocusEffect^7() ^2activated") end
|
||||
Wait(1000)
|
||||
AnimpostfxPlay('FocusIn', 0, true)
|
||||
Wait(30000)
|
||||
AnimpostfxStop('FocusIn')
|
||||
focusEffect = false
|
||||
if Config.Debug then print("^5Debug^7: ^3FocusEffect^7() ^2stopped") end
|
||||
end
|
||||
local NightVisionEffect = false
|
||||
function NightVisionEffect()
|
||||
if NightVisionEffect then return else NightVisionEffect = true end
|
||||
if Config.Debug then print("^5Debug^7: ^3NightVisionEffect^7() ^2activated") end
|
||||
SetNightvision(true)
|
||||
Wait(math.random(3000, 4000)) -- FEEL FREE TO CHANGE THIS
|
||||
SetNightvision(false)
|
||||
SetSeethrough(false)
|
||||
NightVisionEffect = false
|
||||
if Config.Debug then print("^5Debug^7: ^3NightVisionEffect^7() ^2stopped") end
|
||||
end
|
||||
local thermalEffect = false
|
||||
function ThermalEffect()
|
||||
if thermalEffect then return else thermalEffect = true end
|
||||
if Config.Debug then print("^5Debug^7: ^3ThermalEffect^7() ^2activated") end
|
||||
SetNightvision(true)
|
||||
SetSeethrough(true)
|
||||
Wait(math.random(2000, 3000)) -- FEEL FREE TO CHANGE THIS
|
||||
SetNightvision(false)
|
||||
SetSeethrough(false)
|
||||
thermalEffect = false
|
||||
if Config.Debug then print("^5Debug^7: ^3ThermalEffect^7() ^2stopped") end
|
||||
end
|
||||
|
||||
--Built-in Buff effects
|
||||
local healEffect = false
|
||||
function HealEffect(data)
|
||||
if healEffect then return end
|
||||
if Config.Debug then print("^5Debug^7: ^3HealEffect^7() ^2activated") end
|
||||
healEffect = true
|
||||
local count = (data[1] / 1000)
|
||||
while count > 0 do
|
||||
Wait(1000)
|
||||
count -= 1
|
||||
SetEntityHealth(PlayerPedId(), GetEntityHealth(PlayerPedId()) + data[2])
|
||||
end
|
||||
healEffect = false
|
||||
if Config.Debug then print("^5Debug^7: ^3HealEffect^7() ^2stopped") end
|
||||
end
|
||||
|
||||
local staminaEffect = false
|
||||
function StaminaEffect(data)
|
||||
if staminaEffect then return end
|
||||
if Config.Debug then print("^5Debug^7: ^3StaminaEffect^7() ^2activated") end
|
||||
staminaEffect = true
|
||||
local startStamina = (data[1] / 1000)
|
||||
SetRunSprintMultiplierForPlayer(PlayerId(), 1.49)
|
||||
while startStamina > 0 do
|
||||
Wait(1000)
|
||||
if math.random(5, 100) < 10 then RestorePlayerStamina(PlayerId(), data[2]) end
|
||||
startStamina -= 1
|
||||
if math.random(5, 100) < 51 then end
|
||||
end
|
||||
startStamina = 0
|
||||
SetRunSprintMultiplierForPlayer(PlayerId(), 1.0)
|
||||
staminaEffect = false
|
||||
if Config.Debug then print("^5Debug^7: ^3StaminaEffect^7() ^2stopped") end
|
||||
end
|
||||
|
||||
function StopEffects() -- Used to clear up any effects stuck on screen
|
||||
if Config.Debug then print("^5Debug^7: ^2All screen effects stopped") end
|
||||
ShakeGameplayCam('DRUNK_SHAKE', 0.0)
|
||||
SetPedToRagdoll(PlayerPedId(), 5000, 1000, 1, 0, 0, 0)
|
||||
ClearTimecycleModifier()
|
||||
ResetScenarioTypesEnabled()
|
||||
ResetPedMovementClipset(PlayerPedId(), 0)
|
||||
SetPedIsDrunk(PlayerPedId(), false)
|
||||
SetPedMotionBlur(PlayerPedId(), false)
|
||||
SetNightvision(false)
|
||||
SetSeethrough(false)
|
||||
AnimpostfxStop("DrugsMichaelAliensFightIn")
|
||||
AnimpostfxStop("DrugsMichaelAliensFight")
|
||||
AnimpostfxStop("DrugsMichaelAliensFightOut")
|
||||
AnimpostfxStop("DrugsTrevorClownsFight")
|
||||
AnimpostfxStop("DrugsTrevorClownsFightIn")
|
||||
AnimpostfxStop("DrugsTrevorClownsFightOut")
|
||||
AnimpostfxStop('RaceTurbo')
|
||||
AnimpostfxStop('FocusIn')
|
||||
AnimpostfxStop('Rampage')
|
||||
end
|
||||
|
||||
local time = 1000
|
||||
function loadModel(model) if not HasModelLoaded(model) then
|
||||
if Config.Debug then print("^5Debug^7: ^3loadModel^7(): ^2Loading Model^7: '^6"..model.."^7'") end
|
||||
while not HasModelLoaded(model) do
|
||||
if time > 0 then time = time - 1 RequestModel(model)
|
||||
else time = 1000 print("^5Debug^7: ^3loadModel^7(): ^2Timed out loading model ^7'^6"..model.."^7'") break
|
||||
end
|
||||
Wait(10)
|
||||
end
|
||||
end
|
||||
end
|
||||
function unloadModel(model) if Config.Debug then print("^5Debug^7: ^2Removing Model^7: '^6"..model.."^7'") end SetModelAsNoLongerNeeded(model) end
|
||||
function loadAnimDict(dict) if Config.Debug then print("^5Debug^7: ^2Loading Anim Dictionary^7: '^6"..dict.."^7'") end while not HasAnimDictLoaded(dict) do RequestAnimDict(dict) Wait(5) end end
|
||||
function unloadAnimDict(dict) if Config.Debug then print("^5Debug^7: ^2Removing Anim Dictionary^7: '^6"..dict.."^7'") end RemoveAnimDict(dict) end
|
||||
function loadPtfxDict(dict) if Config.Debug then print("^5Debug^7: ^2Loading Ptfx Dictionary^7: '^6"..dict.."^7'") end while not HasNamedPtfxAssetLoaded(dict) do RequestNamedPtfxAsset(dict) Wait(5) end end
|
||||
function unloadPtfxDict(dict) if Config.Debug then print("^5Debug^7: ^2Removing Ptfx Dictionary^7: '^6"..dict.."^7'") end RemoveNamedPtfxAsset(dict) end
|
||||
|
||||
function lookEnt(entity)
|
||||
if type(entity) == "vector3" then
|
||||
if not IsPedHeadingTowardsPosition(PlayerPedId(), entity, 10.0) then
|
||||
TaskTurnPedToFaceCoord(PlayerPedId(), entity, 1500)
|
||||
if Config.Debug then print("^5Debug^7: ^3lookEnt^7(): ^2Turning Player to^7: '^6"..json.encode(entity).."^7'") end
|
||||
Wait(1500)
|
||||
end
|
||||
else
|
||||
if DoesEntityExist(entity) then
|
||||
if not IsPedHeadingTowardsPosition(PlayerPedId(), GetEntityCoords(entity), 30.0) then
|
||||
TaskTurnPedToFaceCoord(PlayerPedId(), GetEntityCoords(entity), 1500)
|
||||
if Config.Debug then print("^5Debug^7: ^3lookEnt^7(): ^2Turning Player to^7: '^6"..entity.."^7'") end
|
||||
Wait(1500)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function makeProp(data, freeze, synced)
|
||||
loadModel(data.prop)
|
||||
local prop = CreateObject(data.prop, data.coords.x, data.coords.y, data.coords.z-1.03, synced or false, synced or false, false)
|
||||
SetEntityHeading(prop, data.coords.w)
|
||||
FreezeEntityPosition(prop, freeze or 0)
|
||||
if Config.Debug then
|
||||
local coords = { string.format("%.2f", data.coords.x), string.format("%.2f", data.coords.y), string.format("%.2f", data.coords.z), (string.format("%.2f", data.coords.w or 0.0)) }
|
||||
print("^5Debug^7: ^1Prop ^2Created^7: '^6"..prop.."^7' | ^2Hash^7: ^7'^6"..(data.prop).."^7' | ^2Coord^7: ^5vec4^7(^6"..(coords[1]).."^7, ^6"..(coords[2]).."^7, ^6"..(coords[3]).."^7, ^6"..(coords[4]).."^7)")
|
||||
end
|
||||
return prop
|
||||
end
|
||||
|
||||
function makePed(model, coords, freeze, collision, scenario, anim)
|
||||
loadModel(model)
|
||||
local ped = CreatePed(0, model, coords.x, coords.y, coords.z-1.03, coords.w, false, false)
|
||||
SetEntityInvincible(ped, true)
|
||||
SetBlockingOfNonTemporaryEvents(ped, true)
|
||||
FreezeEntityPosition(ped, freeze or true)
|
||||
if collision then SetEntityNoCollisionEntity(ped, PlayerPedId(), false) end
|
||||
if scenario then TaskStartScenarioInPlace(ped, scenario, 0, true) end
|
||||
if anim then
|
||||
loadAnimDict(anim[1])
|
||||
TaskPlayAnim(ped, anim[1], anim[2], 1.0, 1.0, -1, 1, 0.2, 0, 0, 0)
|
||||
end
|
||||
if Config.Debug then
|
||||
local coords = { string.format("%.2f", coords.x), string.format("%.2f", coords.y), string.format("%.2f", coords.z), (string.format("%.2f", coords.w or 0.0)) }
|
||||
print("^5Debug^7: ^1Ped ^2Created^7: '^6"..ped.."^7' | ^2Hash^7: ^7'^6"..(model).."^7' | ^2Coord^7: ^5vec4^7(^6"..(coords[1]).."^7, ^6"..(coords[2]).."^7, ^6"..(coords[3]).."^7, ^6"..(coords[4]).."^7)")
|
||||
end
|
||||
return ped
|
||||
end
|
||||
|
||||
function makeBlip(data)
|
||||
local blip = AddBlipForCoord(data.coords)
|
||||
SetBlipAsShortRange(blip, true)
|
||||
SetBlipSprite(blip, data.sprite or 1)
|
||||
SetBlipColour(blip, data.col or 0)
|
||||
SetBlipScale(blip, data.scale or 0.7)
|
||||
SetBlipDisplay(blip, (data.disp or 6))
|
||||
if data.category then SetBlipCategory(blip, data.category) end
|
||||
BeginTextCommandSetBlipName('STRING')
|
||||
AddTextComponentString(tostring(data.name))
|
||||
EndTextCommandSetBlipName(blip)
|
||||
if Config.Debug then print("^5Debug^7: ^6Blip ^2created for location^7: '^6"..data.name.."^7'") end
|
||||
return blip
|
||||
end
|
||||
|
||||
function triggerNotify(title, message, type, src)
|
||||
if not src then TriggerEvent("QBCore:Notify", message, type)
|
||||
else TriggerClientEvent("QBCore:Notify", src, message, type) end
|
||||
end
|
||||
|
||||
function pairsByKeys(t) local a = {} for n in pairs(t) do a[#a+1] = n end table.sort(a) local i = 0 local iter = function() i += 1 if a[i] == nil then return nil else return a[i], t[a[i]] end end return iter end
|
||||
|
||||
function searchCar(vehicle)
|
||||
local newName = nil
|
||||
for k, v in pairs(QBCore.Shared.Vehicles) do
|
||||
if tonumber(v.hash) == GetHashKey(vehicle) then
|
||||
if Config.Debug then print("^5Debug^7: ^2Vehicle info found in^7 ^4vehicles^7.^4lua^7: ^6"..v.hash.. " ^7(^6"..QBCore.Shared.Vehicles[k].name.."^7)") end
|
||||
newName = QBCore.Shared.Vehicles[k].name.." "..QBCore.Shared.Vehicles[k].brand
|
||||
end
|
||||
end
|
||||
if Config.Debug then
|
||||
if not newName then print("^5Debug^7: ^2Vehicle ^1not ^2found in ^4vehicles^7.^4lua^7: ^6"..vehicle.." ^7(^6"..GetDisplayNameFromVehicleModel(vehicle):lower().."^7)") end
|
||||
end
|
||||
if not newName then
|
||||
local name = GetDisplayNameFromVehicleModel(vehicle):lower()
|
||||
local brand = GetMakeNameFromVehicleModel(vehicle):lower()
|
||||
newName = name:sub(1,1):upper()..name:sub(2).." "..brand:sub(1,1):upper()..brand:sub(2)
|
||||
end
|
||||
return newName
|
||||
end
|
||||
|
||||
function HasItem(items, amount)
|
||||
local isTable = type(items) == 'table'
|
||||
local isArray = isTable and table.type(items) == 'array' or false
|
||||
local totalItems = #items
|
||||
local count = 0
|
||||
local kvIndex = 2
|
||||
if Config.Debug then print("^5Debug^7: ^3HasItem^7: ^2Checking if player has required items") end
|
||||
if isTable and not isArray then totalItems = 0
|
||||
for _ in pairs(items) do totalItems += 1 end
|
||||
kvIndex = 1
|
||||
end
|
||||
for _, itemData in pairs(QBCore.Functions.GetPlayerData().items) do
|
||||
if isTable then
|
||||
for k, v in pairs(items) do
|
||||
local itemKV = {k, v}
|
||||
if itemData and itemData.name == itemKV[kvIndex] and ((amount and itemData.amount >= amount) or (not isArray and itemData.amount >= v) or (not amount and isArray)) then
|
||||
count += 1
|
||||
end
|
||||
end
|
||||
if count == totalItems then
|
||||
if Config.Debug then print("^5Debug^7: ^3HasItem^7: ^2Items ^2FOUND^7") end
|
||||
return true
|
||||
end
|
||||
else -- Single item as string
|
||||
if itemData and itemData.name == items and (not amount or (itemData and amount and itemData.amount >= amount)) then
|
||||
if Config.Debug then print("^5Debug^7: ^3HasItem^7: ^2Item^7: '^3"..tostring(items).."^7' ^2FOUND^7") end
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
if Config.Debug then print("^5Debug^7: ^3HasItem^7: ^2Items ^1NOT FOUND^7") end
|
||||
return false
|
||||
end
|
82
resources/[jims]/jim-jobgarage/README.md
Normal file
@ -0,0 +1,82 @@
|
||||
# jim-jobgarage
|
||||
Job garage for grabbing job related vehicles
|
||||
|
||||
---
|
||||
# What is this?
|
||||
- This is a dynamic system for pulling out job and grade locked vehicles
|
||||
- **It's not for parking and saving your vehicles, that is done in your garage scripts**
|
||||
|
||||

|
||||

|
||||
|
||||
### If you need support I have a discord server available, it helps me keep track of issues and give better support.
|
||||
https://discord.gg/xKgQZ6wZvS
|
||||
|
||||
### If you think I did a good job here, consider donating as it keeps by lights on and my cat fat/floofy:
|
||||
https://ko-fi.com/jixelpatterns
|
||||
|
||||
---
|
||||
# Installation
|
||||
|
||||
- I always recommend starting my scripts **AFTER** `[qb]` not inside it as it can mess with any dependancies on server load
|
||||
- I have a separate folder called `[jim]` (that is also in the resources folder) that starts WAY after everything else.
|
||||
- This ensure's it has everything it requires before trying to load
|
||||
- Example of my load order:
|
||||
```CSS
|
||||
# QBCore & Extra stuff
|
||||
ensure qb-core
|
||||
ensure [qb]
|
||||
ensure [standalone]
|
||||
ensure [voice]
|
||||
ensure [defaultmaps]
|
||||
ensure [vehicles]
|
||||
|
||||
# Extra Jim Stuff
|
||||
ensure [jim]
|
||||
```
|
||||
|
||||
---
|
||||
## Location Setup
|
||||
|
||||
- Vehicle Modifiers - These can be used for making sure the vehicles comes out exactly how you want it to
|
||||
- `CustomName = "Police Car",` this will show a custom override name for your vehicles so you don't need to add them to your vehicles.lua
|
||||
- `rank = { 2, 4 },` This specifes which grades can see it, and only these grades
|
||||
- `grade = 4,` This specifies the lowest grade and above that can see the vehicle
|
||||
- `colors = { 136, 137 },` This is the colour index id of the vehicle, Primary and Secondary in that order
|
||||
- `bulletproof = true,` This determines if the tyres are bullet proof (don't ask me why, I was asked to add this)
|
||||
- `livery = 1,` This sets the livery id of the vehicle, (most mod menus would number them or have them in number order) 0 = stock
|
||||
- `extras = { 1, 5 },` -- This enables the selected extras on the vehicle
|
||||
- `performance = "max",` -- This sets the car upgrades all to MAX levels
|
||||
- `performance = { 2, 3, 3, 2, 4, true },` -- This allows more specific settings for each upgrade level, in order: engine, brakes, suspension, transmission, armour, turbo
|
||||
- `trunkItems = { },` -- Use this to add items to the trunk of the vehicle when it is spawned
|
||||
|
||||
- Example:
|
||||
```lua
|
||||
Locations = {
|
||||
{ zoneEnable = true, -- disable if you want to hide this temporarily
|
||||
job = "mechanic", -- set this to required job grade
|
||||
garage = {
|
||||
spawn = vector4(-179.34, -1285.27, 30.83, 89.24), -- Where the vehicle will spawn
|
||||
out = vector4(-177.1, -1282.25, 31.3, 179.01), -- Where you select the vehicles from
|
||||
ped = { -- Add a "ped" table to make a ped spawn instead of the parking meter
|
||||
model = `G_M_M_ChemWork_01`, -- set ped model here
|
||||
scenario = "WORLD_HUMAN_CLIPBOARD" -- set scenario here
|
||||
},
|
||||
list = { -- The list of cars that will spawn
|
||||
["cheburek"] = {
|
||||
CustomName = "Police Car",
|
||||
colors = { 136, 137 }, -- Color index numbers { primary, secondary },
|
||||
grade = 4, -- Job Grade Required to access this vehicle
|
||||
performance = { 2, 3, 3, 2, 4, true },
|
||||
trunkItems = {
|
||||
{ name = "heavyarmor", amount = 2, info = {}, type = "item", slot = 1, },
|
||||
{ name = "empty_evidence_bag", amount = 10, info = {}, type = "item", slot = 2, },
|
||||
{ name = "police_stormram", amount = 1, info = {}, type = "item", slot = 3, },
|
||||
},
|
||||
},
|
||||
["burrito3"] = { }, -- Don't need to add any modifiers/restrictions
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
```
|
216
resources/[jims]/jim-jobgarage/client.lua
Normal file
@ -0,0 +1,216 @@
|
||||
local QBCore = exports['qb-core']:GetCoreObject()
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
|
||||
QBCore.Functions.GetPlayerData(function(PlayerData) PlayerJob = PlayerData.job end)
|
||||
end)
|
||||
RegisterNetEvent('QBCore:Client:OnJobUpdate', function(JobInfo) PlayerJob = JobInfo end)
|
||||
|
||||
AddEventHandler('onResourceStart', function(r) if GetCurrentResourceName() ~= r then return end
|
||||
QBCore.Functions.GetPlayerData(function(PlayerData) PlayerJob = PlayerData.job end)
|
||||
end)
|
||||
|
||||
for i = 1, #Config.Locations do -- Convert trunk items to usable stashes
|
||||
for k, v in pairs(Config.Locations[i].garage.list) do
|
||||
if v.trunkItems then
|
||||
local items = {}
|
||||
for _, item in pairs(v.trunkItems) do
|
||||
local itemInfo = QBCore.Shared.Items[item.name:lower()]
|
||||
items[item.slot] = {
|
||||
name = itemInfo["name"],
|
||||
amount = tonumber(item.amount),
|
||||
info = item.info,
|
||||
label = itemInfo["label"],
|
||||
description = itemInfo["description"] and itemInfo["description"] or "",
|
||||
weight = itemInfo["weight"],
|
||||
type = itemInfo["type"],
|
||||
unique = itemInfo["unique"],
|
||||
useable = itemInfo["useable"],
|
||||
image = itemInfo["image"],
|
||||
slot = item.slot,
|
||||
}
|
||||
end
|
||||
Config.Locations[i].garage.list[k].trunkItems = items
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local Targets = {}
|
||||
local Parking = {}
|
||||
|
||||
--Garage Locations
|
||||
CreateThread(function()
|
||||
for k, v in pairs(Config.Locations) do
|
||||
if v.garage then
|
||||
local out = v.garage.out
|
||||
if v.garage.ped then Parking[#Parking+1] = makePed(v.garage.ped.model, out, 1, 1, v.garage.ped.scenario)
|
||||
else Parking[#Parking+1] = makeProp({prop = `prop_parkingpay`, coords = vector4(out.x, out.y, out.z, out.w-180.0)}, 1, false) end
|
||||
Targets["JobGarage: "..k] =
|
||||
exports['qb-target']:AddBoxZone("JobGarage: "..k, vector3(out.x, out.y, out.z-1.03), 0.8, 0.5, { name="JobGarage: "..k, heading = out.w+180.0, debugPoly=Config.Debug, minZ=out.z-1.05, maxZ=out.z+0.80 },
|
||||
{ options = { { event = "jim-jobgarage:client:Garage:Menu", icon = "fas fa-clipboard", label = "Firmabiler", job = v.job, coords = v.garage.spawn, list = v.garage.list, prop = Parking[#Parking] }, },
|
||||
distance = 2.0 })
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local currentVeh = { out = false, current = nil }
|
||||
RegisterNetEvent('jim-jobgarage:client:Garage:Menu', function(data)
|
||||
if not IsPedInAnyVehicle(PlayerPedId()) then
|
||||
lookEnt(data.prop)
|
||||
loadAnimDict("amb@prop_human_atm@male@enter")
|
||||
TaskPlayAnim(PlayerPedId(), 'amb@prop_human_atm@male@enter', "enter", 1.0,-1.0, 1500, 1, 1, true, true, true)
|
||||
end
|
||||
local vehicleMenu = { { icon = "fas fa-car-tunnel", header = PlayerJob.label.." ".."Firmagarage", isMenuHeader = true } }
|
||||
vehicleMenu[#vehicleMenu+1] = { icon = "fas fa-circle-xmark", header = "", txt = "Luk", params = { event = "jim-jobgarage:client:Menu:Close" } }
|
||||
if currentVeh.out and DoesEntityExist(currentVeh.current) then
|
||||
vehicleMenu[#vehicleMenu+1] = { icon = "fas fa-clipboard-list", header = "Køretøj ude af garage",
|
||||
txt = "Køretøj: "..currentVeh.name.."<br> Plate: ["..GetVehicleNumberPlateText(currentVeh.current).."]",
|
||||
params = { event = "jim-jobgarage:client:Garage:Blip", }, }
|
||||
vehicleMenu[#vehicleMenu+1] = { icon = "fas fa-car-burst", header = "Fjern køretøj", params = { event = "jim-jobgarage:client:RemSpawn" } }
|
||||
else
|
||||
currentVeh = { out = false, current = nil }
|
||||
table.sort(data.list, function(a, b) return a:lower() < b:lower() end)
|
||||
for k, v in pairsByKeys(data.list) do
|
||||
local showButton = false
|
||||
if v.grade then if v.grade <= PlayerJob.grade.level then showButton = true end end
|
||||
if v.rank then for _, b in pairs(v.rank) do if b == PlayerJob.grade.level then showButton = true end end end
|
||||
if not v.grade and not v.rank then showButton = true end
|
||||
if showButton == true then
|
||||
local spawnName = k local spawnHash = GetHashKey(spawnName)
|
||||
--k = data.list[spawnName].CustomName or searchCar(spawnName)
|
||||
local classtable = {
|
||||
[8] = "fas fa-motorcycle", -- Motorcycle icon
|
||||
[9] = "fas fa-truck-monster", -- Off Road icon
|
||||
[10] = "fas fa-truck-front", -- Van / Truck icon
|
||||
[11] = "fas fa-truck-front", -- Van / Truck icon
|
||||
[12] = "fas fa-truck-front", -- Van / Truck icon
|
||||
[13] = "fas fa-bicycle", -- Bike
|
||||
[14] = "fas fa-ship", -- Boats
|
||||
[15] = "fas fa-helicopter",-- Helicopter
|
||||
[16] = "fas fa-plane", -- Planes
|
||||
[18] = "fas fa-kit-medical", -- Emergency
|
||||
}
|
||||
local seticon = classtable[GetVehicleClassFromName(spawnHash)] or "fas fa-car"
|
||||
vehicleMenu[#vehicleMenu+1] = { icon = seticon, header = (data.list[k].CustomName or searchCar(k)), params = { event = "jim-jobgarage:client:SpawnList", args = { spawnName = spawnName, coords = data.coords, list = v } } }
|
||||
end
|
||||
end
|
||||
end
|
||||
showButton = nil
|
||||
if #vehicleMenu <= 2 then triggerNotify(nil, "Ingen køretøjer tilgængelig") return end
|
||||
exports['qb-menu']:openMenu(vehicleMenu)
|
||||
unloadAnimDict("amb@prop_human_atm@male@enter")
|
||||
end)
|
||||
|
||||
RegisterNetEvent("jim-jobgarage:client:SpawnList", function(data)
|
||||
local oldveh = GetClosestVehicle(data.coords.x, data.coords.y, data.coords.z, 2.5, 0, 71)
|
||||
local name = ""
|
||||
if oldveh ~= 0 then
|
||||
name = searchCar(GetEntityModel(oldveh))
|
||||
triggerNotify(nil, name.." er i vejen", "error")
|
||||
else
|
||||
QBCore.Functions.SpawnVehicle(data.spawnName, function(veh)
|
||||
local name = data.list.CustomName or searchCar(data.spawnName)
|
||||
currentVeh = { out = true, current = veh, name = name }
|
||||
SetVehicleModKit(veh, 0)
|
||||
NetworkRequestControlOfEntity(veh)
|
||||
SetVehicleNumberPlateText(veh, string.sub(PlayerJob.label, 1, 5)..tostring(math.random(100, 999)))
|
||||
--SetVehicleNumberPlateText(veh, "PD-"..QBCore.Functions.GetPlayerData().metadata.callsign)
|
||||
SetEntityHeading(veh, data.coords.w)
|
||||
TaskWarpPedIntoVehicle(PlayerPedId(), veh, -1)
|
||||
if data.list.colors then SetVehicleColours(veh, data.list.colors[1], data.list.colors[2]) end
|
||||
if data.list.bulletproof then SetVehicleTyresCanBurst(veh, false) end
|
||||
if data.list.extras then
|
||||
for _, v in pairs(data.list.extras) do SetVehicleExtra(veh, v, 0) end
|
||||
end
|
||||
if data.list.livery then
|
||||
if GetNumVehicleMods(veh, 48) == 0 and GetVehicleLiveryCount(veh) ~= 0 then
|
||||
SetVehicleLivery(veh, data.list.livery)
|
||||
SetVehicleMod(veh, 48, -1, false)
|
||||
else
|
||||
SetVehicleMod(veh, 48, (data.list.livery - 1), false)
|
||||
SetVehicleLivery(veh, -1)
|
||||
end
|
||||
end
|
||||
|
||||
if data.list.turbo then ToggleVehicleMod(veh, 18, data.list.turbo) end
|
||||
if data.list.xenon then ToggleVehicleMod(veh, 22, data.list.xenon) end
|
||||
if data.list.mod42 then SetVehicleMod(veh, 42, (data.list.mod42-1), false) end
|
||||
if data.list.mod43 then SetVehicleMod(veh, 43, (data.list.mod43-1), false) end
|
||||
if data.list.mod44 then SetVehicleMod(veh, 44, (data.list.mod44-1), false) end
|
||||
if data.list.mod45 then SetVehicleMod(veh, 45, (data.list.mod45-1), false) end
|
||||
if data.list.mod49 then SetVehicleMod(veh, 49, (data.list.mod49-1), false) end
|
||||
|
||||
if data.list.performance then
|
||||
if type(data.list.performance) ~= "table" then
|
||||
SetVehicleMod(veh, 11, GetNumVehicleMods(veh, 11)-1) -- Engine
|
||||
SetVehicleMod(veh, 12, GetNumVehicleMods(veh, 12)-1) -- Brakes
|
||||
SetVehicleMod(veh, 15, GetNumVehicleMods(veh, 15)-1) -- Suspension
|
||||
SetVehicleMod(veh, 13, GetNumVehicleMods(veh, 13)-1) -- Transmission
|
||||
SetVehicleMod(veh, 16, GetNumVehicleMods(veh, 16)-1) -- Armour
|
||||
ToggleVehicleMod(veh, 18, true) -- Turbo
|
||||
else
|
||||
SetVehicleMod(veh, 11, data.list.performance[1]-1) -- Engine
|
||||
SetVehicleMod(veh, 12, data.list.performance[2]-1) -- Brakes
|
||||
SetVehicleMod(veh, 15, data.list.performance[3]-1) -- Suspension
|
||||
SetVehicleMod(veh, 13, data.list.performance[4]-1) -- Transmission
|
||||
SetVehicleMod(veh, 16, data.list.performance[5]-1) -- Armour
|
||||
ToggleVehicleMod(veh, 18, data.list.performance[6]) -- Turbo
|
||||
end
|
||||
end
|
||||
if data.list.trunkItems then TriggerServerEvent("jim-jobgarage:server:addTrunkItems", QBCore.Functions.GetPlate(veh), data.list.trunkItems) end
|
||||
TriggerEvent("vehiclekeys:client:SetOwner", QBCore.Functions.GetPlate(veh))
|
||||
exports['qb-fuel']:SetFuel(veh, 100.0)
|
||||
SetVehicleEngineOn(veh, true, true)
|
||||
Wait(250)
|
||||
SetVehicleDirtLevel(veh, 0.0)
|
||||
triggerNotify(nil, "Tog "..name.." ["..GetVehicleNumberPlateText(currentVeh.current).."]", "success")
|
||||
end, data.coords, true)
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent("jim-jobgarage:client:RemSpawn", function(data)
|
||||
if Config.CarDespawn then
|
||||
SetVehicleEngineHealth(currentVeh.current, 200.0)
|
||||
SetVehicleBodyHealth(currentVeh.current, 200.0)
|
||||
for i = 0, 7 do SmashVehicleWindow(currentVeh.current, i) Wait(150) end PopOutVehicleWindscreen(currentVeh.current)
|
||||
for i = 0, 5 do SetVehicleTyreBurst(currentVeh.current, i, true, 0) Wait(150) end
|
||||
for i = 0, 5 do SetVehicleDoorBroken(currentVeh.current, i, false) Wait(150) end
|
||||
Wait(800)
|
||||
end
|
||||
QBCore.Functions.DeleteVehicle(currentVeh.current) currentVeh = { out = false, current = nil }
|
||||
end)
|
||||
|
||||
local markerOn = false
|
||||
RegisterNetEvent("jim-jobgarage:client:Garage:Blip", function(data)
|
||||
triggerNotify(nil, "Firmabil markeret på kortet")
|
||||
if markerOn then markerOn = not markerOn end
|
||||
markerOn = true
|
||||
if not DoesBlipExist(garageBlip) then
|
||||
garageBlip = makeBlip({ coords = GetEntityCoords(currentVeh.current), sprite = 85, col = 8, name = "Firmabil" })
|
||||
SetBlipRoute(garageBlip, true)
|
||||
SetBlipRouteColour(garageBlip, 3)
|
||||
end
|
||||
while markerOn do
|
||||
local time = 5000
|
||||
local carLoc = GetEntityCoords(currentVeh.current)
|
||||
local playerLoc = GetEntityCoords(PlayerPedId())
|
||||
if DoesEntityExist(currentVeh.current) then
|
||||
local dist = #(carLoc - playerLoc)
|
||||
if dist <= 30.0 and dist > 1.5 then time = 1000
|
||||
elseif dist <= 1.5 then
|
||||
RemoveBlip(garageBlip)
|
||||
garageBlip = nil
|
||||
markerOn = not markerOn
|
||||
else time = 5000 end
|
||||
else
|
||||
RemoveBlip(garageBlip)
|
||||
garageBlip = nil
|
||||
markerOn = not markerOn
|
||||
end
|
||||
Wait(time)
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler('onResourceStop', function(r) if r ~= GetCurrentResourceName() then return end
|
||||
for k in pairs(Targets) do exports['qb-target']:RemoveZone(k) end
|
||||
for i = 1, #Parking do unloadModel(GetEntityModel(Parking[i])) DeleteEntity(Parking[i]) end
|
||||
end)
|
128
resources/[jims]/jim-jobgarage/config.lua
Normal file
@ -0,0 +1,128 @@
|
||||
--[[ LIST OF POSSIBLE VEHICLE MODIFIERS ]]--
|
||||
-- Using these will change how each vehicle spawns
|
||||
-- This can be used for making sure the vehicles comes out exactly how you want it to
|
||||
|
||||
-- CustomName = "Police Car", this will show a custom override name for your vehicles so you don't need to add them to your vehicles.lua
|
||||
-- rank = { 2, 4 }, -- This specifes which grades can see it, and only these grades
|
||||
-- grade = 4, -- This specifies the lowest grade and above that can see the vehicle
|
||||
-- colors = { 136, 137 }, -- This is the colour index id of the vehicle, Primary and Secondary in that order
|
||||
-- bulletproof = true, -- This determines if the tyres are bullet proof (don't ask me why, I was asked to add this)
|
||||
-- livery = 1, -- This sets the livery id of the vehicle, (most mod menus would number them or have them in number order) 0 = stock
|
||||
-- extras = { 1, 5 }, -- This enables the selected extras on the vehicle
|
||||
-- performance = "max", this sets the stats to max if available
|
||||
-- performance = { 2, 3, 3, 2, 4, true }, -- This allows more specific settings for each upgrade level, in order: engine, brakes, suspension, transmission, armour, turbo
|
||||
-- trunkItems = { }, -- Use this to add items to the trunk of the vehicle when it is spawned
|
||||
|
||||
-- ANY VEHICLE, BOATS, POLICE CARS, EMS VEHICLES OR EVEN PLANES CAN BE ADDED.
|
||||
|
||||
Config = {
|
||||
Debug = false, -- Enable to use debug features
|
||||
Notify = "qb",
|
||||
CarDespawn = true, -- Sends the vehicle to hell
|
||||
Locations = {
|
||||
{
|
||||
zoneEnable = true,
|
||||
job = "police",
|
||||
garage = {
|
||||
spawn = vector4(430.77, -980.06, 25.14, 183.81),
|
||||
out = vector4(427.75, -988.33, 25.14, 273.73),
|
||||
list = {
|
||||
["polgauntlet"] = {
|
||||
CustomName = "Gauntlet Interceptor",
|
||||
grade = 0,
|
||||
colors = { 91, 132 },
|
||||
livery = 19,
|
||||
extras = { 3 },
|
||||
turbo = true,
|
||||
xenon = true,
|
||||
mod42 = 1,
|
||||
mod43 = 7,
|
||||
performance = "max",
|
||||
trunkItems = {
|
||||
{ name = "heavyarmor", amount = 2, info = {}, type = "item", slot = 1, },
|
||||
{ name = "empty_evidence_bag", amount = 10, info = {}, type = "item", slot = 2, },
|
||||
{ name = "police_stormram", amount = 1, info = {}, type = "item", slot = 3, },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
zoneEnable = true, -- disable if you want to hide this temporarily
|
||||
job = "police", -- set this to required job grade
|
||||
garage = {
|
||||
spawn = vector4(447.65, -981.21, 43.69, 93.61), -- Where the vehicle will spawn
|
||||
out = vector4(463.93, -980.53, 43.69, 97.02), -- Where you select the vehicles from
|
||||
list = { -- The list of cars that will spawn
|
||||
["polmav"] = {
|
||||
CustomName = "Politihelikopter",
|
||||
livery = 0,
|
||||
extras = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 },
|
||||
performance = "max",
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
zoneEnable = true, -- disable if you want to hide this temporarily
|
||||
job = "ambulance", -- set this to required job grade
|
||||
garage = {
|
||||
spawn = vector4(351.58, -587.45, 74.16, 160.5), -- Where the vehicle will spawn
|
||||
out = vector4(337.3927, -586.7730, 74.1617, 250.08), -- Where you select the vehicles from
|
||||
list = { -- The list of cars that will spawn
|
||||
["polmav"] = {
|
||||
CustomName = "Lægehelikopter",
|
||||
livery = 1,
|
||||
extras = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 },
|
||||
performance = "max",
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
zoneEnable = true, -- disable if you want to hide this temporarily
|
||||
job = "ambulance", -- set this to required job grade
|
||||
garage = {
|
||||
spawn = vector4(290.21, -572.13, 43.2, 75.99), -- Where the vehicle will spawn
|
||||
out = vector4(293.33, -567.13, 43.26, 157.69), -- Where you select the vehicles from
|
||||
list = { -- The list of cars that will spawn
|
||||
["ambulance"] = {
|
||||
CustomName = "Ambulance",
|
||||
livery = 1,
|
||||
extras = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 },
|
||||
performance = "max",
|
||||
},
|
||||
["21yuk"] = {
|
||||
CustomName = "EMS SUV",
|
||||
livery = 1,
|
||||
extras = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 },
|
||||
performance = "max",
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
zoneEnable = true,
|
||||
job = "gardener",
|
||||
garage = {
|
||||
spawn = vector4(967.95, -1019.72, 40.85, 271.94),
|
||||
out = vector4(963.88, -1016.92, 40.85, 270.38),
|
||||
list = {
|
||||
["bison3"] = {
|
||||
CustomName = "Redskabsvogn",
|
||||
grade = 0,
|
||||
colors = { 131, 131 },
|
||||
livery = 19,
|
||||
extras = { 3 },
|
||||
turbo = true,
|
||||
xenon = true,
|
||||
performance = "max",
|
||||
trunkItems = {
|
||||
{ name = "shears", amount = 1, info = {}, type = "item", slot = 1, },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
130
resources/[jims]/jim-jobgarage/functions.lua
Normal file
@ -0,0 +1,130 @@
|
||||
local QBCore = exports['qb-core']:GetCoreObject()
|
||||
RegisterNetEvent('QBCore:Client:UpdateObject', function() QBCore = exports['qb-core']:GetCoreObject() end)
|
||||
|
||||
local time = 1000
|
||||
function loadModel(model) if not HasModelLoaded(model) then
|
||||
if Config.Debug then print("^5Debug^7: ^2Loading Model^7: '^6"..model.."^7'") end
|
||||
while not HasModelLoaded(model) do
|
||||
if time > 0 then time -= 1 RequestModel(model)
|
||||
else time = 1000 print("^5Debug^7: ^3LoadModel^7: ^2Timed out loading model ^7'^6"..model.."^7'") break
|
||||
end
|
||||
Wait(10)
|
||||
end
|
||||
end end
|
||||
function unloadModel(model) if Config.Debug then print("^5Debug^7: ^2Removing Model^7: '^6"..model.."^7'") end SetModelAsNoLongerNeeded(model) end
|
||||
function loadAnimDict(dict) if not HasAnimDictLoaded(dict) then if Config.Debug then print("^5Debug^7: ^2Loading Anim Dictionary^7: '^6"..dict.."^7'") end while not HasAnimDictLoaded(dict) do RequestAnimDict(dict) Wait(5) end end end
|
||||
function unloadAnimDict(dict) if Config.Debug then print("^5Debug^7: ^2Removing Anim Dictionary^7: '^6"..dict.."^7'") end RemoveAnimDict(dict) end
|
||||
function loadPtfxDict(dict) if not HasNamedPtfxAssetLoaded(dict) then if Config.Debug then print("^5Debug^7: ^2Loading Ptfx Dictionary^7: '^6"..dict.."^7'") end while not HasNamedPtfxAssetLoaded(dict) do RequestNamedPtfxAsset(dict) Wait(5) end end end
|
||||
function unloadPtfxDict(dict) if Config.Debug then print("^5Debug^7: ^2Removing Ptfx Dictionary^7: '^6"..dict.."^7'") end RemoveNamedPtfxAsset(dict) end
|
||||
|
||||
|
||||
function destroyProp(entity)
|
||||
if Config.Debug then print("^5Debug^7: ^2Destroying Prop^7: '^6"..entity.."^7'") end
|
||||
SetEntityAsMissionEntity(entity) Wait(5)
|
||||
DetachEntity(entity, true, true) Wait(5)
|
||||
DeleteEntity(entity)
|
||||
end
|
||||
|
||||
function makeProp(data, freeze, synced)
|
||||
loadModel(data.prop)
|
||||
local prop = CreateObject(data.prop, data.coords.x, data.coords.y, data.coords.z-1.03, synced or 0, synced or false, false)
|
||||
SetEntityHeading(prop, data.coords.w)
|
||||
FreezeEntityPosition(prop, freeze or 0)
|
||||
if Config.Debug then print("^5Debug^7: ^6Prop ^2Created ^7: '^6"..prop.."^7'") end
|
||||
return prop
|
||||
end
|
||||
|
||||
function makePed(model, coords, freeze, collision, scenario, anim)
|
||||
loadModel(model)
|
||||
local ped = CreatePed(0, model, coords.x, coords.y, coords.z-1.03, coords.w, false, false)
|
||||
SetEntityInvincible(ped, true)
|
||||
SetBlockingOfNonTemporaryEvents(ped, true)
|
||||
FreezeEntityPosition(ped, freeze or true)
|
||||
if collision then SetEntityNoCollisionEntity(ped, PlayerPedId(), false) end
|
||||
if scenario then TaskStartScenarioInPlace(ped, scenario, 0, true) end
|
||||
if anim then
|
||||
loadAnimDict(anim[1])
|
||||
TaskPlayAnim(ped, anim[1], anim[2], 1.0, 1.0, -1, 1, 0.2, 0, 0, 0)
|
||||
end
|
||||
if Config.Debug then print("^5Debug^7: ^6Ped ^2Created for location^7: '^6"..model.."^7'") end
|
||||
return ped
|
||||
end
|
||||
|
||||
function makeBlip(data)
|
||||
local blip = AddBlipForCoord(data.coords)
|
||||
SetBlipAsShortRange(blip, true)
|
||||
SetBlipSprite(blip, data.sprite or 1)
|
||||
SetBlipColour(blip, data.col or 0)
|
||||
SetBlipScale(blip, data.scale or 0.7)
|
||||
SetBlipDisplay(blip, (data.disp or 6))
|
||||
BeginTextCommandSetBlipName('STRING')
|
||||
AddTextComponentString(tostring(data.name))
|
||||
EndTextCommandSetBlipName(blip)
|
||||
if Config.Debug then print("^5Debug^7: ^6Blip ^2created for location^7: '^6"..data.name.."^7'") end
|
||||
return blip
|
||||
end
|
||||
|
||||
function lookEnt(entity)
|
||||
if type(entity) == "vector3" then
|
||||
if not IsPedHeadingTowardsPosition(PlayerPedId(), entity, 10.0) then
|
||||
TaskTurnPedToFaceCoord(PlayerPedId(), entity, 1500)
|
||||
if Config.Debug then print("^5Debug^7: ^2Turning Player to^7: '^6"..json.encode(entity).."^7'") end
|
||||
Wait(1500)
|
||||
end
|
||||
else
|
||||
if DoesEntityExist(entity) then
|
||||
if not IsPedHeadingTowardsPosition(PlayerPedId(), GetEntityCoords(entity), 30.0) then
|
||||
TaskTurnPedToFaceCoord(PlayerPedId(), GetEntityCoords(entity), 1500)
|
||||
if Config.Debug then print("^5Debug^7: ^2Turning Player to^7: '^6"..entity.."^7'") end
|
||||
Wait(1500)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function triggerNotify(title, message, type, src)
|
||||
if Config.Notify == "okok" then
|
||||
if not src then exports['okokNotify']:Alert(title, message, 6000, type or 'info')
|
||||
else TriggerClientEvent('okokNotify:Alert', src, title, message, 6000, type or 'info') end
|
||||
elseif Config.Notify == "qb" then
|
||||
if not src then TriggerEvent("QBCore:Notify", message, type)
|
||||
else TriggerClientEvent("QBCore:Notify", src, message, type) end
|
||||
elseif Config.Notify == "t" then
|
||||
if not src then exports['t-notify']:Custom({title = title, style = type, message = message, sound = true})
|
||||
else TriggerClientEvent('t-notify:client:Custom', src, { style = type, duration = 6000, title = title, message = message, sound = true, custom = true}) end
|
||||
elseif Config.Notify == "infinity" then
|
||||
if not src then TriggerEvent('infinity-notify:sendNotify', message, type)
|
||||
else TriggerClientEvent('infinity-notify:sendNotify', src, message, type) end
|
||||
elseif Config.Notify == "rr" then
|
||||
if not src then exports.rr_uilib:Notify({msg = message, type = type, style = "dark", duration = 6000, position = "top-right", })
|
||||
else TriggerClientEvent("rr_uilib:Notify", src, {msg = message, type = type, style = "dark", duration = 6000, position = "top-right", }) end
|
||||
end
|
||||
end
|
||||
|
||||
function pairsByKeys(t)
|
||||
local a = {}
|
||||
for n in pairs(t) do a[#a+1] = n end
|
||||
table.sort(a)
|
||||
local i = 0
|
||||
local iter = function() i += 1 if a[i] == nil then return nil else return a[i], t[a[i]] end end
|
||||
return iter
|
||||
end
|
||||
|
||||
function searchCar(vehicle)
|
||||
newName = nil
|
||||
for k, v in pairs(QBCore.Shared.Vehicles) do
|
||||
if tonumber(v.hash) == vehicle then
|
||||
if Config.Debug then print("^5Debug^7: ^2Vehicle info found in^7 ^4vehicles^7.^4lua^7: ^6"..v.hash.. " ^7(^6"..QBCore.Shared.Vehicles[k].name.."^7)") end
|
||||
newName = QBCore.Shared.Vehicles[k].name.." "..QBCore.Shared.Vehicles[k].brand
|
||||
end
|
||||
end
|
||||
if Config.Debug then
|
||||
if not newName then print("^5Debug^7: ^2Vehicle ^1not ^2found in ^4vehicles^7.^4lua^7: ^6"..vehicle.." ^7(^6"..GetDisplayNameFromVehicleModel(vehicle):lower().."^7)") end
|
||||
end
|
||||
if not newName then
|
||||
local name = GetDisplayNameFromVehicleModel(vehicle):lower()
|
||||
local brand = GetMakeNameFromVehicleModel(vehicle):lower()
|
||||
newName = name:sub(1,1):upper()..name:sub(2).." "..brand:sub(1,1):upper()..brand:sub(2)
|
||||
end
|
||||
return newName
|
||||
end
|
12
resources/[jims]/jim-jobgarage/fxmanifest.lua
Normal file
@ -0,0 +1,12 @@
|
||||
name "Jim-JobGarage"
|
||||
author "Jimathy"
|
||||
version "v1.3.2"
|
||||
description "Job Garage Script By Jimathy"
|
||||
fx_version 'cerulean'
|
||||
game "gta5"
|
||||
|
||||
client_scripts { 'client.lua', }
|
||||
server_scripts { 'server.lua'}
|
||||
shared_scripts { 'config.lua', 'functions.lua' }
|
||||
|
||||
lua54 'yes'
|
1
resources/[jims]/jim-jobgarage/server.lua
Normal file
@ -0,0 +1 @@
|
||||
RegisterNetEvent("jim-jobgarage:server:addTrunkItems", function(plate, items) exports["ps-inventory"]:addTrunkItems(plate, items) end)
|