Wert Dev Docs
Tebex StoreDiscord
  • ℹ️About Us
  • Products
    • QBCore
      • Wert Pd Roster
      • Wert Jewel Robbery V2
      • Wert Jammer
      • Wert Gps V2
      • Wert Ammunation Jobs
      • Wert Jobs V2
      • Wert Contactless Payment
      • Wert GoPro (Watch vehicles with gopros)
      • Wert Shop Robbery
      • Wert Shops + Delivery Jobs (Buy and manage your shops)
      • Wert Houses
      • Wert Ambulance Job
      • Wert BodyCam (For civilians and jobs)
      • Wert Police Systems V2
      • Wert ChopShop V2
      • Wert Taboo (Play and enjoy)
      • Wert illegal house robbery
      • Wert Banking (Bank ui and system)
      • Wert Paleto Bank Robbery V2
      • Wert Car Arena (Death race, Death match, Arena war)
      • Wert Blackmarket Phone
      • Wert Gang Zone (Advanced Npc System)
      • Wert Fuel Stations (Job, Buy, Manage, Create and more ... )
      • Wert Craft System
      • Wert Merryweather Job
      • Wert Cleaning System And Jobs
      • Wert Weapon Racks (Deployable, Advanced)
      • Wert Water Dispensers (Coolers)
      • Wert Lucky Wheel
      • Wert Evidence System
      • Wert Give Money System
      • Wert Ems Roster System
      • Wert New Year Lottery
      • Wert Vending Machines
    • ESX
      • Wert Shop Robbery
      • Wert Jewel Robbery V2
      • Wert Gps V2
      • Wert Police Systems V2
      • Wert Jobs V2
      • Wert Contactless Payment
      • Wert GoPro (Watch vehicles with gopros)
      • Wert Ammunation Jobs
      • Wert BodyCam (For civilians and jobs)
      • Wert ChopShop V2
      • Wert Taboo (Play and enjoy)
      • Wert illegal house robbery
      • Wert Paleto Bank Robbery V2
      • Wert Jammer
      • Wert Car Arena (Death race, Death match, Arena war)
      • Wert Banking (Bank ui and system)
      • Wert Fuel Stations (Job, Buy, Manage, Create and more ... )
      • Wert Gang Zone (Advanced Npc System)
      • Wert Blackmarket Phone
      • Wert Craft System
      • Wert Merryweather Job
      • Wert Cleaning System And Jobs
      • Wert Weapon Racks (Deployable, Advanced)
      • Wert Water Dispensers (Coolers)
      • Wert Lucky Wheel
      • Wert Evidence System
      • Wert Give Money System
      • Wert Ems Roster System
      • Wert New Year Lottery
      • Wert Pd Roster
      • Wert Vending Machines
      • Wert Ambulance Job
    • Qbox
      • Wert Pd Roster
      • Wert Jewel Robbery V2
      • Wert Jammer
      • Wert Gps V2
      • Wert Ammunation Jobs
      • Wert Jobs V2
      • Wert Contactless Payment
      • Wert GoPro (Watch vehicles with gopros)
      • Wert Shop Robbery
      • Wert Shops + Delivery Jobs (Buy and manage your shops)
      • Wert Houses
      • Wert Ambulance Job
      • Wert BodyCam (For civilians and jobs)
      • Wert Police Systems V2
      • Wert-ChopShopV2
      • Wert Taboo (Play and enjoy)
      • Wert illegal house robbery
      • Wert Banking (Bank ui and system)
      • Wert Paleto Bank Robbery V2
      • Wert Car Arena (Death race, Death match, Arena war)
      • Wert Blackmarket Phone
      • Wert Gang Zone (Advanced Npc System)
      • Wert Fuel Stations (Job, Buy, Manage, Create and more ... )
      • Wert Craft System
      • Wert Merryweather Job
      • Wert Cleaning System And Jobs
      • Wert Weapon Racks (Deployable, Advanced)
      • Wert Water Dispensers (Coolers)
      • Wert Lucky Wheel
      • Wert Evidence System
      • Wert Give Money System
      • Wert Ems Roster System
      • Wert New Year Lottery
      • Wert Vending Machines
    • STANDALONE
      • Wert Npc Dialog System
      • Wert Racing Hud
Powered by GitBook
On this page
  • INSTALLATION
  • OX LIB OPTION
  • INFORMATION
  • OPEN FILES
  1. Products
  2. ESX

Wert Ems Roster System

You can access the setup information you need about this product

PreviousWert Give Money SystemNextWert New Year Lottery

Last updated 6 months ago

INSTALLATION

1 - Upload the script folder to the location of your resources

2 - Check config and editable file settings. If you are using different systems, you can make the necessary adjustments in these files, such as for , ox_lib, etc.

3 - Load emsroster.sql file in ur database.

4 - Installation successful, have a good funs

OX LIB OPTION

There are many ox settings available in the files, if you want, you can configure them.

If you want to use ox_lib, please check if this link is enabled on fxmanifest.check it out from inside lua. this must be turned on before you can use ox_lib. After opening it, it will be enough to use the refresh and ensure commands.

Also be sure open this connection in fxmanifest.lua

INFORMATION

The script comes with default settings. There are many settings in the configuration file, and you can customize all of them to your personal preferences. Below are the configuration files, feel free to check them out.

OPEN FILES

Config  = {}

Config.UseTarget = true -- # If u want use target set true | true or false | boolean | (editable_client have more option for select target system)
Config.OxLib = true -- # If u want use ox lib set true | true or false | boolean
Config.DebugPoly = false -- # If you want draw zones set true | true or false | boolean

-- # No target interaction key
Config.NoTargetInteractionKey = 38 -- https://docs.fivem.net/docs/game-references/controls/

-- # Search players jobs (Players who have which job will be shown in the Roster)
Config.WhitelistJobs = {
    ['ambulance'] = true,
}

-- # Roster open settings
Config.OpenRosterCommand = {
    active = true, -- If you want to open the roster with command | true or false | boolean
    command = 'emsroster', -- Command name
    description = 'Open ems roster tablet!', -- Command description
    job = {
        ['ambulance'] = 0, -- [jobname] = mingrade for open
    }
}

Config.OpenRosterKey = { -- Hotkey for open ems roster
    active = true, -- If you want to open the roster with key | true or false | boolean
    key = 'F10', -- Key : https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/keyboard/
    description = 'Open ems roster tablet!', -- Key description
    job = {
        ['ambulance'] = 0, -- [jobname] = mingrade for open
    }
}

Config.OpenRosterZones = { -- Open target infos
    {
        coord = vector3(310.3, -593.22, 43.28),
        sizeA = 0.8,
        sizeB = 1.0,
        heading = 0,
        minZ = 42.28,
        maxZ = 44.28,
        icon = 'fa-solid fa-laptop',
        label = 'Roster',
        job = {['ambulance'] = 0}, -- If u want edit here for more job or if u want add grade check like : job = {['ambulamce'] = 0}
        distance = 1.5, -- Interaction size, If u use no target please set correct coord and this is interaction size. | If u use target it's target distance
        isComputer = true, -- If going to perform an access via a computer, make it true computer animation takes place. | true or false | boolean
    },
}

-- # Staff (Boss) menu settings and zones
-- !IMPORTANT : Don't forget edit the boss grade levels for ur job list. If u change anything in ur job list.
Config.BossMenuCommand = {
    active = true, -- If you want to open the roster staff with command | true or false | boolean
    command = 'emsrosterstaff', -- Command name
    description = 'Ems roster staff menu!', -- Command description
    job = {
        ['ambulance'] = 4, -- [jobname] = mingrade for open
    }
} 

Config.BossMenuZones = {
    {
        coord = vector3(335.48, -594.48, 43.28),
        sizeA = 1.4,
        sizeB = 1.0,
        heading = 340,
        minZ = 42.28,
        maxZ = 44.28,
        icon = 'fa-solid fa-server',
        label = 'Personel database',
        job = {['ambulance'] = 4}, -- If u want edit here for more job or if u want add grade check like : job = {['ambulamce'] = 4}
        distance = 1.5, -- Interaction size, If u use no target please set correct coord and this is interaction size. | If u use target it's target distance
        isComputer = true, -- If going to perform an access via a computer, make it true computer animation takes place. | true or false | boolean
    },
}

-- # Open object and animation settings
Config.TabletModel = `prop_cs_tablet`
Config.TabletAnimationSettings = {
    dict = "amb@code_human_in_bus_passenger_idles@female@tablet@idle_a",
    clip = "idle_a",
    flag = 50,
}
Config.TabletObjectSettings = {
    bone = 28422,
    pos = {-0.05, 0.0, 0.0}, -- Position
    rot = {0.0, 0.0, 0.0}, -- Rotation
}
Config.ComputerAnimationSettings = {
    dict = "mp_prison_break",
    clip = "hack_loop",
    flag = 49,
}

-- # Badge Settings
-- If u want edit here what u want. If u want select specific icon from https://fontawesome.com/icons or if u want edit for image. What u want exactly ...
Config.BadgeSettings = {
    -- [Grade] = inner
    ['0'] = '<i class="fa-solid fa-star"></i>',
    ['1'] = '<i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i>',
    ['2'] = '<i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i>',
    ['3'] = '<i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i>',
    ['4'] = '<i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i>',
}

-- # Department settings
-- If u want add more or edit specializations here ...
Config.Departments = {
    -- [value] = label
    ["emergency"] = "Emergency",
    ["surgery"] = "Surgery",
    ["cardiology"] = "Cardiology",
    ["orthopedics"] = "Orthopedics",
    ["pediatrics"] = "Pediatrics",
    ["neurology"] = "Neurology",
    ["internalmedicine"] = "Internal Medicine",
    ["dermatology"] = "Dermatology",
    ["anesthesiology"] = "Anesthesiology",
    ["psychiatry"] = "Psychiatry",
    ["gastroenterology"] = "Gastroenterology",
    ["ophthalmology"] = "Ophthalmology",
    ["gynecology"] = "Gynecology",
    ["otolaryngology"] = "Otolaryngology",
    ["urology"] = "Urology",
    ["radiology"] = "Radiology",
    ["oncology"] = "Oncology",
    ["infectiousdiseases"] = "Infectious Diseases",
    ["physiotherapy"] = "Physiotherapy",
    -- Nothing option for the default this is requid | If u want edit default table in config
    ['nothing'] = 'Not Selected',
}

-- # Specialization settings
-- If u want add more or edit specializations here ...
Config.Specializations = {
    -- [value] = label
    ["cardiologist"] = "Cardiologist",
    ["orthopedicsurgeon"] = "Orthopedic Surgeon",
    ["neurologist"] = "Neurologist",
    ["pediatrician"] = "Pediatrician",
    ["oncologist"] = "Oncologist",
    ["generalsurgeon"] = "General Surgeon",
    ["psychiatrist"] = "Psychiatrist",
    ["dermatologist"] = "Dermatologist",
    ["endocrinologist"] = "Endocrinologist",
    ["anesthesiologist"] = "Anesthesiologist",
    ["gastroenterologist"] = "Gastroenterologist",
    ["pulmonologist"] = "Pulmonologist",
    ["ophthalmologist"] = "Ophthalmologist",
    ["physiotherapist"] = "Physiotherapist",
    -- Nothing option for the default this is requid | If u want edit default table in config
    ['nothing'] = 'Nothing',
}


-- # Status settings
-- If u want add more or edit statuses here ...
Config.Statuses = {
    -- [value] = label
    ['active'] = 'Active',
    ['deactive'] = 'Deactive',
    -- Nothing option for the default this is requid | If u want edit default table in config
    ['nothing'] = 'Uncertain',
}


-- # Default datas (If player not have saved data before time ...)
Config.DefaultDatas = {
    badgeno = 'NOT',
    department = 'nothing', -- Must be a valid value in Config.Departments table
    rank = 'None',
    ranklevel = 0, -- Must be number
    specialization = 'nothing', -- Must be a valid value in Config.Specializations 
    surgeries = 0, -- Must be number
    activitytime = 0, -- Must be number
    consultations = 0, -- Must be number
    certificates = 'None',
    status = 'nothing',
    picture = nil, -- If u want change default picture for everyone u can change with string
}
local ESX = exports["es_extended"]:getSharedObject()
local PlayerJob = nil

-- # Functions

function GetJobData()
    local mydata = ESX.GetPlayerData()
    if not mydata then return 'unemployed', 0 end
    local jobname = mydata.job.name
    local grade = mydata.job.grade and tonumber(mydata.job.grade) or 0
    return jobname, grade
end

function CustomNotifVariation(text, style, time)
    ESX.ShowNotification(text, style or 'info', time or 3000)
end

function ShowTextUI(text)
    if Config.OxLib then
        lib.showTextUI(text, {position = 'left-center'})
    else
        -- # If u use another system if u want edit here
    end
end

function HideTextUI()
    if Config.OxLib then
        lib.hideTextUI()
    else
        -- # If u use another system if u want edit here
    end
end

function CustomTargetAddBoxZone(data, options)
    exports.ox_target:addBoxZone({
        name = data.name,
        coords = data.coord,
        size = vec3(data.sizeA, data.sizeB, data.sizeA),
        rotation = data.heading,
        debug = Config.DebugPoly, 
        options = options
    })
end

-- # Events

RegisterNetEvent('wert-emsroster:client:custom-notify', function(text, style, time)
    CustomNotifVariation(text, style, time)
end)

RegisterNetEvent('esx:playerLoaded', function()
    Wait(1000)
    PlayerJob = ESX.GetPlayerData().job.name
    TriggerServerEvent('wert-emsroster:server:ply-join-game')
end)

RegisterNetEvent('esx:setJob', function(JobInfo)
    local old_job = PlayerJob
    PlayerJob = JobInfo.name
    if Config.WhitelistJobs[old_job] or Config.WhitelistJobs[PlayerJob] then TriggerServerEvent('wert-emsroster:server:ply-update-job', old_job) end
end)

AddEventHandler('onResourceStart', function(resource)
    if resource == GetCurrentResourceName() then
        Wait(1000)
        PlayerJob = ESX.GetPlayerData().job.name
        TriggerServerEvent('wert-emsroster:server:ply-join-game')
    end
end)
local ESX = exports["es_extended"]:getSharedObject()
local TimeData = {}

function CustomGetPlayerWithSource(src)
    if not src then return nil end
    return ESX.GetPlayerFromId(src)
end

function CustomGetOnlinePlayers()
    local mergePlayers = {}
    local players = ESX.GetPlayers()
    for k,v in pairs(players) do
        local ply = ESX.GetPlayerFromId(v)
        if ply then mergePlayers[#mergePlayers+1] = ply end
    end
    return mergePlayers
end

function CustomGetPlayerWithIdentifier(identifier)
    return ESX.GetPlayerFromIdentifier(identifier)
end

function GetPlayerJobAndGrade(ply)
    if not ply then return 'unemployed', 0 end
    local job = ply.job.name
    local grade = ply.job.grade and tonumber(ply.job.grade) or 0
    return job, grade
end

function GetOnlinePlayerData(ply)
    if not ply or not Config.WhitelistJobs[ply.job.name] then return nil end
    local data = {fullname = nil, jobData = nil}
    local myjob = ply.job
    data.fullname = ply.getName()
    data.jobData = {onduty = true, grade = {name = myjob.grade_label, level = myjob.grade}}
    return data
end

function GetFullNameForOnlinePlayer(ply)
    return ply.getName()
end

function GetDutyStatusForOnlinePlayer(ply)
    -- If u use a duty system u can make intergate
    return true
end

function OfflineFindGradeLabel(jobname, gradelevel)
    local myLabel = 'Undefined'
    local jobs = ESX.GetJobs()
    local findTable = jobs[jobname]
    if findTable and findTable.grades then
        local convLevel = tostring(gradelevel)
        if findTable.grades[convLevel] then
            myLabel = findTable.grades[convLevel].label or 'Undefined'
        end
    end
    return myLabel
end

function GetOfflinePlayerData(identifier)
    local response = MySQL.query.await('SELECT `firstname`, `lastname`, `job`, `job_grade` FROM `users` WHERE `citizenid` = ?', {identifier})
    if not response or not response[1] then return nil end
    local data = {fullname = nil, jobData = nil}
    local plyJobName = response[1].job
    local plyJobGradeLevel = response[1].job_grade and tonumber(response[1].job_grade) or 0
    local plyJobGradeLabel = OfflineFindGradeLabel(plyJobName, plyJobGradeLevel)
    data.fullname = response[1].firstname .. ' ' .. response[1].lastname
    data.jobData = {onduty = false, grade = {name = plyJobGradeLabel, level = plyJobGradeLevel}}
    return data
end

function GetAllPlayersFromSql()
    local likeClauses = {}
	for jobname, jobstate in pairs(Config.WhitelistJobs) do likeClauses[#likeClauses+1] = "`job` LIKE '%" .. jobname .. "%'" end
	local whereClause = table.concat(likeClauses, " OR ")
        local players = MySQL.query.await("SELECT identifier, job, firstname, lastname, job_grade FROM `users` WHERE " .. whereClause, {})
    return players
end

function GetOfflinePlayerDataWithRow(value)
    if not value then return nil end
    local data = {fullname = nil, jobData = nil}
    local plyJobName = value.job
    local plyJobGradeLevel = value.job_grade and tonumber(value.job_grade) or 0
    local plyJobGradeLabel = OfflineFindGradeLabel(plyJobName, plyJobGradeLevel)
    data.fullname = value.firstname .. ' ' .. value.lastname
    data.jobData = {onduty = false, grade = {name = plyJobGradeLabel, level = plyJobGradeLevel}}
    return data
end

function ActivityTimeInterval()
    local players = CustomGetOnlinePlayers()
    for k, ply in pairs(players) do
        if ply and Config.WhitelistJobs[ply.job.name] then
            local src = tostring(ply.source)
            if TimeData[src] then
                local citizenid = ply.getIdentifier()
                local now = os.time()
                local secondDiff = os.difftime(now, TimeData[src])
                exports['wert-emsroster']:AddUserData(citizenid, 'activitytime', tonumber(secondDiff))
                TimeData[src] = os.time()
            end
        end
    end
    SetTimeout(5 * (60 * 1000), ActivityTimeInterval)
end

-- # If u have a duty system please intergate
--[[ RegisterNetEvent('QBCore:Server:SetDuty', function(id, duty)
    if not id then return end
    local src = tonumber(id)
    local ply = CustomGetPlayerWithSource(src)
    if not ply then return end
    if not Config.WhitelistJobs[ply.job.name] then return end
    local citizenid = ply.getIdentifier()
    id = tostring(id)
    if duty then
        TimeData[id] = os.time()
    elseif not duty and TimeData[id] then
        local old_data = TimeData[id]
        TimeData[id] = nil
        local now = os.time()
        local secondDiff = os.difftime(now, old_data)
        exports['wert-emsroster']:AddUserData(citizenid, 'activitytime', tonumber(secondDiff))
    end
end) ]]

RegisterNetEvent('wert-emsroster:server:ply-join-game', function()
    local src = source
    local ply = CustomGetPlayerWithSource(src)
    if not ply then return end
    if not Config.WhitelistJobs[ply.job.name] then return end
    local id = tostring(src)
    TimeData[id] = os.time()
end)

RegisterNetEvent('wert-emsroster:server:ply-update-job', function(oldjob)
    local src = source
    Wait(1000)
    local ply = CustomGetPlayerWithSource(src)
    if not ply then return end
    local id = tostring(src)
    local jobname = ply.job.name
    if not Config.WhitelistJobs[jobname] and TimeData[id] then
        TimeData[id] = nil
    elseif Config.WhitelistJobs[jobname] and not TimeData[id] then
        TimeData[id] = os.time()
    end
end)

AddEventHandler('playerDropped', function(reason)
    local src = source
    local conv = tostring(src)
    if TimeData[conv] then TimeData[conv] = nil end
end)

CreateThread(function()
    Wait(3000)
    ActivityTimeInterval()
end)
LANG = {
    error = {
        permission_error = 'You do not have permission for the this action!',
    },
    interaction = {
        notargetOpen = '[E] Open Ems Roster',
        notargetBossmenu = '[E] Open Ems Roster Boss Menu',
    },
    ui = {
        induty = 'In Duty',
        offduty = 'Off Duty',
        activityTime = '%s Hour.',
        certificate_popui_label = '%s Certificates',
        certificate_popui_close = 'Close',
        labels = {
            badgeno = 'Badge No',
            name = 'Name',
            department = 'Department',
            rank = 'Rank',
            badge = 'Badge',
            specialization = 'Specialization',
            duty = 'Duty',
            surgeries = 'Surgeries',
            activitytime = 'Activity Time',
            consultations = 'Consultations',
            certificates = 'Certificates',
            status = 'Status',
        },
        bossmenu = {
            noData = 'No personnel data found!',
            clickDesc = 'Click for more information',
            label = 'EMS ROSTER EDITOR',
            placeholder = 'Search Player',
            informationHeader = 'Welcome, %s (%s)',
            informationText = 'From this menu, you can edit the roster data of EMS personnel. You can check and edit the listed individuals in the area below. Simply click the corresponding button to edit.',
            save = 'Save Datas',
            badgeno_placeholder = 'Select Badge No',
            surgeries_placeholder = 'Select Surgeries',
            consultations_placeholder = 'Select Consultations',
            certificates_placeholder = 'Add Certificates',
            editlabel_badgeno = 'Badge No',
            editlabel_department = 'Department',
            editlabel_specialization = 'Specialization',
            editlabel_surgeries = 'Surgeries',
            editlabel_consultations = 'Consultations',
            editlabel_certificates = 'Certificates',
            editlabel_status = 'Status',
            userdataerrorheader = 'User Not Found!',
            userdataerrordescription = 'User data not found from database. Please refresh and try again!',
            refresherrorheader = 'Datas Not Loaded!',
            refresherrordescription = 'An error occurred while fetching the data, please try again later.',
            refreshedHeader = 'Page Has Been Updated!',
            refreshedDescription = 'Success! You can continue work on page.',
            saveactionfailedheader = 'Save Failed!',
            saveactionfaileddescription = 'Registration failed due to an unknown error, try again later!',
            savedheader = 'User Saved!',
            saveddescription = 'Successfully! User informations saved.',
            editlabel_picture = 'Picture',
            picture_placeholder = 'Picture URL',
        }
    },
    time = {
        less_than_minute = "0 min.",
        minute_and_seconds = "%d min. %d sec.",
        hours_and_minutes = "%d hour, %d min.",
        day_and_hours = "%d day, %d hour."
    },
}