Wert Dev Docs
Tebex StoreDiscord
  • ℹ️About Us
  • Products
    • QBCore
      • Wert-pdroster
      • Wert-JewelRobberyV2
      • Wert-jammer
      • Wert-GpsV2
      • Wert-AmmunationJobs
      • Wert-JobsV2
      • Wert-ContactlessPayment
      • Wert-GoPro (Watch vehicles with gopros)
      • Wert-ShopRobbery
      • Wert-shops + delivery jobs (Buy and manage your shops)
      • Wert-houses
      • Wert-ambulancejob
      • Wert-BodyCam (For civilians and jobs)
      • Wert-PoliceSystemsV2
      • Wert-ChopShopV2
      • Wert-taboo (Play and enjoy)
      • Wert illegal house robbery
      • Wert-banking (Bank ui and system)
      • Wert-PaletoBankRobberyV2
      • 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-ShopRobbery
      • Wert-JewelRobberyV2
      • Wert-GpsV2
      • Wert-PoliceSystemsV2
      • Wert-JobsV2
      • Wert-ContactlessPayment
      • Wert-GoPro (Watch vehicles with gopros)
      • Wert-AmmunationJobs
      • Wert-BodyCam (For civilians and jobs)
      • Wert-ChopShopV2
      • Wert-taboo (Play and enjoy)
      • Wert illegal house robbery
      • Wert-PaletoBankRobberyV2
      • 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-pdroster
      • Wert Vending Machines
    • Qbox
      • Wert-pdroster
      • Wert-JewelRobberyV2
      • Wert-jammer
      • Wert-GpsV2
      • Wert-AmmunationJobs
      • Wert-JobsV2
      • Wert-ContactlessPayment
      • Wert-GoPro (Watch vehicles with gopros)
      • Wert-ShopRobbery
      • Wert-shops + delivery jobs (Buy and manage your shops)
      • Wert-houses
      • Wert-ambulancejob
      • Wert-BodyCam (For civilians and jobs)
      • Wert-PoliceSystemsV2
      • Wert-ChopShopV2
      • Wert-taboo (Play and enjoy)
      • Wert illegal house robbery
      • Wert-banking (Bank ui and system)
      • Wert-PaletoBankRobberyV2
      • 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. Qbox

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 = false -- # 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 QBCore = exports['qb-core']:GetCoreObject()
local PlayerJob = nil

-- # Functions

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

function CustomNotifVariation(text, style, time)
    QBCore.Functions.Notify(text, style, time)
end

function ShowTextUI(text)
    if Config.OxLib then
        lib.showTextUI(text, {position = 'left-center'})
    else
        exports['qb-core']:DrawText(text, 'left')
    end
end

function HideTextUI()
    if Config.OxLib then
        lib.hideTextUI()
    else
        exports['qb-core']:HideText()
    end
end

function CustomTargetAddBoxZone(data, options)
    exports['qb-target']:AddBoxZone(data.name, data.coord, data.sizeA, data.sizeB, {
        name = data.name,
        heading = data.heading,
        debugPoly = Config.DebugPoly,
        minZ = data.minZ,
        maxZ = data.maxZ,
    }, { options = options, distance = data.distance })
end

-- # Events

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

RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
    Wait(1000)
    PlayerJob = QBCore.Functions.GetPlayerData().job.name
    TriggerServerEvent('wert-emsroster:server:ply-join-game')
end)

RegisterNetEvent('QBCore:Client:OnJobUpdate', 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 = QBCore.Functions.GetPlayerData().job.name
        TriggerServerEvent('wert-emsroster:server:ply-join-game')
    end
end)
local QBCore = exports['qb-core']:GetCoreObject()
local TimeData = {}

function CustomGetPlayerWithSource(src)
    if not src then return nil end
    return QBCore.Functions.GetPlayer(src)
end

function CustomGetOnlinePlayers()
    return QBCore.Functions.GetQBPlayers()
end

function CustomGetPlayerWithIdentifier(identifier)
    return QBCore.Functions.GetPlayerByCitizenId(identifier)
end

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

function GetOnlinePlayerData(ply)
    if not ply or not Config.WhitelistJobs[ply.PlayerData.job.name] then return nil end
    local data = {fullname = nil, jobData = nil}
    local myjob = ply.PlayerData.job
    data.fullname = ply.PlayerData.charinfo.firstname .. ' ' .. ply.PlayerData.charinfo.lastname
    data.jobData = {onduty = myjob.onduty, grade = {name = myjob.grade.name, level = myjob.grade.level}}
    return data
end

function GetOfflinePlayerData(identifier)
    local response = MySQL.query.await('SELECT `charinfo`, `job` FROM `players` WHERE `citizenid` = ?', {identifier})
    if not response or not response[1] then return nil end
    local data = {fullname = nil, jobData = nil}
    local ply_charinfo = json.decode(response[1].charinfo)
    local ply_job = json.decode(response[1].job)
    data.fullname = ply_charinfo.firstname .. ' ' .. ply_charinfo.lastname
    data.jobData = {onduty = ply_job.onduty, grade = {name = ply_job.grade.name, level = ply_job.grade.level}}
    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 citizenid, job, charinfo FROM `players` WHERE " .. whereClause, {})
    return players
end

function GetOfflinePlayerDataWithRow(value)
    if not value then return nil end
    local data = {fullname = nil, jobData = nil}
    local ply_charinfo = json.decode(value.charinfo)
    local ply_job = json.decode(value.job)
    data.fullname = ply_charinfo.firstname .. ' ' .. ply_charinfo.lastname
    data.jobData = {onduty = ply_job.onduty, grade = {name = ply_job.grade.name, level = ply_job.grade.level}}
    return data
end

function ActivityTimeInterval()
    local players = CustomGetOnlinePlayers()
    for k, ply in pairs(players) do
        if ply and Config.WhitelistJobs[ply.PlayerData.job.name] then
            local src = tostring(ply.PlayerData.source)
            if TimeData[src] then
                local citizenid = ply.PlayerData.citizenid
                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

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.PlayerData.job.name] then return end
    local citizenid = ply.PlayerData.citizenid
    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.PlayerData.job.name] then return end
    if not ply.PlayerData.job.onduty 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) -- Safety delay
    local ply = CustomGetPlayerWithSource(src)
    if not ply then return end
    local id = tostring(src)
    local jobname = ply.PlayerData.job.name
    local myduty = ply.PlayerData.job.onduty
    if not Config.WhitelistJobs[jobname] and TimeData[id] then
        TimeData[id] = nil
    elseif Config.WhitelistJobs[jobname] and not TimeData[id] and myduty 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)


-- # Test for wert
RegisterCommand('addnewplayers', function()
    local characterNames = {
        "Emily",
        "Michael",
        "Sarah",
        "David",
        "Laura",
    }
    local characterLastnames = {
        "Carter",
        "Thompson",
        "Bennett",
        "Green",
        "Mitchell",
    }
    local characterJobDatas = {
        {payment = 150, isboss = true, onduty = false, label = "EMS", type = "ems", name = "ambulance", grade = {name = "Chief", level = 4}},
        {payment = 125, isboss = true, onduty = false, label = "EMS", type = "ems", name = "ambulance", grade = {name = "Surgeon", level = 3}},
        {payment = 100, isboss = true, onduty = false, label = "EMS", type = "ems", name = "ambulance", grade = {name = "Doctor", level = 2}},
        {payment = 75, isboss = true, onduty = false, label = "EMS", type = "ems", name = "ambulance", grade = {name = "Paramedic", level = 1}},
        {payment = 50, isboss = true, onduty = false, label = "EMS", type = "ems", name = "ambulance", grade = {name = "Recruit", level = 0}},
    }
    for i=1, 5 do
        local citizenid = QBCore.Player.CreateCitizenId()
        local account = QBCore.Functions.CreateAccountNumber()
        local phoneNo = QBCore.Functions.CreatePhoneNumber()
        local cid = 1
        local license = 'license:here'
        local name = 'tesply'
        local money = {bank = 5000, cash = 500, crypto = 0}
        local charinfo = {
            nationality = "Turks and Caicos Islands",
            lastname = characterLastnames[i],
            phone = phoneNo,
            gender = 0,
            firstname = characterNames[i],
            cid = 1,
            backstory="placeholder backstory",
            account = account,
            birthdate = "2024-02-08"
        }
        local inventory = {}
        local job = characterJobDatas[i]
        local metadata = {}
        local id = MySQL.insert.await('INSERT INTO `players` (citizenid, cid, license, name, money, charinfo, job, gang, position, metadata, inventory) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', {
            citizenid, cid, license, name, json.encode(money), json.encode(charinfo), json.encode(job), json.encode({}), json.encode({}), json.encode({}), json.encode(inventory)
        })
        Wait(500)
    end
    print('All players loaded')
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."
    },
}