Page cover image

โš™๏ธConfiguration

Discover how to config your script.

Event to Open Multicharacter:

TriggerClientEvent('zr-multicharacter:start', src)

Tutorial of how to get the discord token , guild and roles ids :

Files that are configurable

zr-multicharacter/zr-config/zr-config.lua

zr-multicharacter/zr-config/zr-build-c.lua

zr-multicharacter/zr-config/zr-build-s.lua

To ensure you have everything you need, we are constantly updating our config files.

zr_config.framework = 'QB'  -- We support the following frameworks: 'QB' / 'ESX'
zr_config.QB = 'qb-core'    -- Don't touch
zr_config.ESX = 'es_extended'  -- Don't touch

zr_config.ToggleInterior = true
zr_config.Interior = vector3(-169.286, 486.4938, 137.4436)
zr_config.DefaultSpawn = vector3(-1035.71, -2731.87, 12.86)
zr_config.PlaCoords = vector4(-176.0504, 491.7193, 133.8438, 190.9712)
zr_config.CamCoords = vector4(-176.5, 498.7330, 134.8, 12)
zr_config.EndCoords = vector4(-176.1338, 500.2804, 134.6434, 180)
zr_config.StartCoords = vector4(-179.7581, 499.4727, 134.6435, 281.5096)

zr_config.DefaultModels = {"mp_m_freemode_01","mp_f_freemode_01"}

zr_config.zr_notify = true

zr_config.clothing = 'illenium-appearance' -- 'qb-clothing' or 'illenium-appearance'
zr_config.spawn = 'zr-locations' --  'ps-housing' or 'qb-spawn'


zr_config.default_slots = 1 -- Minimum 1
zr_config.discord_enable = true
-- Token transfered to zr-build-s.lua
zr_config.discord_guild = 1000020530499432448
zr_config.discord_roles = {
    ["1000377003704336476"] = 2, -- Add extra 2 slots if player has this role.
    ["1004486369919373392"] = 1, -- Add extra 1 slot if player has this role.
}

zr_config.EnableDelete = true
zr_config.EnableDeleteByDiscord = false
zr_config.discord_roles_delete_button = {
    ["1000377003704336476"] = true,
    ["1004486369919373392"] = true, 
}

zr_config.Debug = false

zr_config.prefix = 'char'

zr_trans.chinfos = "Character Information."
zr_trans.otinfos = "Other Information."
zr_trans.delete = "Delete character."
zr_trans.deleteconf = "Click again to confirm!"
zr_trans.play = "Play as"
zr_trans.create = "Create new character."
zr_trans.fname = "First Name"
zr_trans.lname = "Last Name"
zr_trans.gender = "Gender"
zr_trans.male = 'MALE'
zr_trans.female = 'FEMALE'
zr_trans.dob = "Birthdate"
zr_trans.job = "Job"
zr_trans.cash = "Cash"
zr_trans.bank = "Bank"
zr_trans.symb = "$"
zr_trans.aslots = "Default slots"
zr_trans.dslots = "Discord slots"

zr_trans.noslots = "You don't have any empty slots!"
zr_trans.deleted = "Character Deleted"
zr_trans.deldiscord = "You must have a discord role to delete your character"

Open Source part of the script that we do provide in order to make your necessary changes for your server compatibility.

function zr_multichar_show_public()
	-- Trigger Custom Functions/Events when display menu.
end

function zr_multichar_hide_public()
	-- Trigger Custom Functions/Events when hide menu.
end

function zr_setup_skin(zr_data)
    DeleteEntity(zr_current_char)
    if (zr_config.framework=='QB') then -- QBcore
        if zr_data ~= nil then
            QBcore.Functions.TriggerCallback('zr-multicharacter:getSkinData', function(zr_model, zr_skin)
				if (zr_config.clothing=='qb-clothing') then
					zr_model = zr_model ~= nil and tonumber(zr_model) or false
				end
				if zr_model ~= nil then
					CreateThread(function()
						zr_skin = json.decode(zr_skin)
						zr_multichar_loadModel(zr_model)
						zr_current_char = CreatePed(2, zr_model, zr_config.StartCoords.x, zr_config.StartCoords.y, zr_config.StartCoords.z, zr_config.StartCoords.w, false, true)
						if (zr_config.clothing=='qb-clothing') then
							TriggerEvent('qb-clothing:client:loadPlayerClothing', zr_skin, zr_current_char)
						elseif (zr_config.clothing=='illenium-appearance') then
							exports['illenium-appearance']:setPedAppearance(zr_current_char, zr_skin)
						end
						zr_animate_character(zr_current_char)
					end)
				else
					CreateThread(function()				
						zr_model = GetHashKey(zr_config.DefaultModels[math.random(1, #zr_config.DefaultModels)])
						zr_multichar_loadModel(zr_model)
						zr_current_char = CreatePed(2, zr_model, zr_config.StartCoords.x, zr_config.StartCoords.y, zr_config.StartCoords.z, zr_config.StartCoords.w, false, true)	
						zr_animate_character(zr_current_char)
					end)
				end
			end, zr_data.citizenid)
        else
            CreateThread(function()
                local zr_model = GetHashKey(zr_config.DefaultModels[1])
                zr_multichar_loadModel(zr_model)
                zr_current_char = CreatePed(2, zr_model, zr_config.StartCoords.x, zr_config.StartCoords.y, zr_config.StartCoords.z, zr_config.StartCoords.w, false, true)	
				zr_animate_character(zr_current_char)
            end)
        end
    else -- ESX
		if zr_data ~= nil then
			local zr_pedtype = "mp_f_freemode_01"
			local zr_skin = zr_config.DefaultSkins["f"]
			zr_skin.sex = 1
			if zr_data.sex == nil then 
				zr_pedtype = "mp_m_freemode_01"
				if zr_pedtype == "mp_m_freemode_01" then 
					zr_skin = zr_config.DefaultSkins["m"]
					zr_skin.sex = 0
				end
			else
				if zr_data.sex == "m" then 
					zr_pedtype = "mp_m_freemode_01"
					zr_skin = zr_config.DefaultSkins["m"]
					zr_skin.sex = 0
				end  
			end
			zr_model = GetHashKey(zr_pedtype)
			if zr_model ~= nil then
				CreateThread(function()
					exports.spawnmanager:spawnPlayer({x = zr_config.StartCoords.x,y = zr_config.StartCoords.y,z = zr_config.StartCoords.z,heading = zr_config.StartCoords.w,model = ped,skipFade = true
					}, function()
						if zr_data.skin then 
							zr_multichar_loadModel(zr_model)
							SetPlayerModel(PlayerId(), zr_model)
							SetModelAsNoLongerNeeded(zr_model)
							TriggerEvent('skinchanger:loadSkin', zr_data.skin)
						else
							TriggerEvent('skinchanger:loadSkin', zr_skin)
						end
					end)
					Wait(500)
					zr_animate_character(PlayerPedId())
				end)
			end
		end         
    end
end

if (zr_config.framework=='ESX') then
    RegisterNetEvent('esx:playerLoaded')
	AddEventHandler('esx:playerLoaded', function(zr_playerdata, zr_isnew, zr_skin)
		local zr_spawn = zr_playerdata.coords or zr_config.DefaultSpawn
		if zr_isnew or not zr_skin or #zr_skin == 1 then
			local done = false
			local zr_gender = zr_playerdata.sex -- local zr_gender = 'm' (https://github.com/zaphosting/esx_12)
			zr_skin = zr_config.DefaultSkins[zr_gender]
			zr_skin.sex = zr_gender == "m" and 0 or 1 
			if zr_skin.sex == 0 then zr_model = zr_config.DefaultModels[1] else zr_model = zr_config.DefaultModels[2] end
			zr_multichar_loadModel(zr_model)
			SetPlayerModel(PlayerId(), zr_model)
			SetModelAsNoLongerNeeded(zr_model)
			TriggerEvent('skinchanger:loadSkin', zr_skin, function()
                TriggerEvent('esx_skin:openSaveableMenu', function()
                    done = true end, function() done = true
                end)
			end)
			repeat Wait(200) until done
		end
		DoScreenFadeOut(100)
		SetEntityCoordsNoOffset(PlayerPedId(), zr_spawn.x, zr_spawn.y, zr_spawn.z, false, false, false, true)
		SetEntityHeading(PlayerPedId(), zr_spawn.heading)
		if not zr_isnew then TriggerEvent('skinchanger:loadSkin', zr_skin) end
		Wait(400)
		DoScreenFadeIn(400)
		repeat Wait(200) until not IsScreenFadedOut()
		TriggerServerEvent('esx:onPlayerSpawn')
		TriggerEvent('esx:onPlayerSpawn')
		TriggerEvent('playerSpawned')
		TriggerEvent('esx:restoreLoadout')
		FreezeEntityPosition(PlayerPedId(), false)
		zr_multichar_esx_hideplayers = false
		zr_multichar_esx_loops_stop()
	end)

	RegisterNetEvent('esx:onPlayerLogout')
	AddEventHandler('esx:onPlayerLogout', function()
		DoScreenFadeOut(0)
		TriggerEvent('esx_skin:resetFirstSpawn')
	end)
end


function zr_identity_notify(zr_msg)
    if (zr_config.zr_notify) then
        exports['zr-notify']:zr_notify('info', zr_msg, 5000, 'info', 'right')
    else
        if (zr_config.framework=='QB') then
            QBcore.Functions.Notify(zr_msg, "info")
		else
			ESX.ShowNotification(zr_msg, "info", 3000)
        end
    end
end
-- Discord Token Moved to Server Side
zr_config.discord_token = "Discord_Token_Here"  

if (zr_config.framework=='QB') then
    QBcore.Functions.CreateCallback("zr-multicharacter:getSkinData", function(_, cb, cid)
        if (zr_config.clothing=='qb-clothing') then
            local zr_data = MySQL.query.await('SELECT * FROM playerskins WHERE citizenid = ? AND active = ?', {cid, 1})
            if zr_data[1] ~= nil then
                cb(zr_data[1].model, zr_data[1].skin)
            else
                cb(nil)
            end
        elseif (zr_config.clothing=='illenium-appearance') then
            local zr_data = MySQL.query.await('SELECT * FROM playerskins WHERE citizenid = ? AND active = ?', {cid, 1})
            if zr_data[1] ~= nil then
                cb(zr_data[1].model, zr_data[1].skin)
            else
                cb(nil)
            end
        end
    end)

    function zr_custom_spawn_menu(zr_source, zr_data)
        if (zr_config.spawn=='ps-housing') then
            TriggerClientEvent('ps-housing:client:setupSpawnUI', zr_source, zr_data)
        else
            TriggerClientEvent('apartments:client:setupSpawnUI', zr_source, zr_data)
        end
    end

    QBcore.Commands.Add("logout", 'logout', {}, false, function(source)
        local src = source
        QBcore.Player.Logout(src)
        TriggerClientEvent('zr-multicharacter:start', src)
    end, "admin")
end


if (zr_config.framework=='ESX') then
    zr_dbtablesesx = {users = 'identifier'}

    function zr_custom_spawn_menu(zr_source)
        -- Spawn menu trigger here! 
    end 

    RegisterCommand('relog', function(source)
        TriggerClientEvent('zr-multicharacter:start', source)
        TriggerEvent('esx:playerLogout', source)
    end)
end

Last updated