Skip to main content

Setting Up The Drug Testing System

Out of the Box

By default, r14-evidence has built-in triggers for the base drug items included with qb-smallresources and an optional config line for jim-consumables. If you have added new, custom drugs to qb-smallreosurces or use a different consumables script for your drug items overal, you will need to either modify your drug resource or examine it to set up the r14-evidence drug testing config to integrate with it. These edits will require adding server event tiggers to properly trigger r14-evidence to set drug status, or finding the server events fired in the script when drugs are used so the config can automatically generate a trigger.

Configuring A Third Party Script

r14-evidence Drug Config
--[[---------- Drug Testing Config ----------

This table allows you to set up or completely disable drug testing in the script, out of the box, r14-evidence is set up to work with the drugs included
in qb-core through built-in event listeners/handlers both in the server and client. If you are using a third party drug script, you can use the EventTriggers
subfield to set up custom event handlers to integreate with your drug/consumables script, or you can follow the guide at regalonefour.github.io to insert
custom event triggers into your drug/consumables resource code in order to trigger the proper drug testing events in r14-evidence.

Below, we will add a sample config for a hypothetical drug script in which were we specify the paramaters that will trigger drug usage.

[4] = {
event = 'customdrugs:server:cocaine', -- REQUIRED IF NOT USING JIMS VARIABLE, name of the event to listen for
drugType = 'cocaine' -- REQUIRED, specify the config drug test that will be set positive by this event trigger
type = 'server', -- OPTIONAL, will default to server if not specified, if you want to use a client event you must specify client
positiveTime = 4, -- OPTIONAL, specify a custom time in hours for the character to return positive
drugArgPos = 4, -- OPTIONAL, if your script uses one event for multiple drugs, you can access an argument to validate the drug
drugArgSubfield = 'drugName', -- OPTIONAL, if your argument is a table, specify the name of the key to be accessed
drugArgValue = 'cocaine', -- OPTIONAL, the value the argument should be to trigger the drug usage, by default this will be true if not specified and you have specified an arg, this can also be a table for multiple drugs
cidArgPos = 2, -- OPTIONAL, if your server event is being triggered by the server for some reason, specify the arg of the player CID, not needed if triggering from client
cidArgSubfield = , -- OPTIONAL, specify the subfield if the arg is a table, not needed if triggering from client, not needed if triggering from client
sourceArgPos = 3, -- OPTIONAL, if your server event is being triggered by the server for some reason, specify the source fo the player to find their CID, not needed if triggering from client
souceArgSubfield = originalSource, -- OPTIONAL, specify the original source subfield if the arg is a table, such as here arg[3].originalSource, not needed if triggering from client
},

--]]------------------------------------------

Config.DrugTesting = {
Enabled = true,
UsingQBSR = true, -- set to true if you are using basic qb-smallresources, if not you will need to specify an event trigger or edit your consumables resource
DefaultPositiveTime = 2, -- number, in hours, that a player remains positive for a drug test (does not extend past script reset)
Drugs = { -- these are DRUG TYPES that show up on your drug test, avoid adding too many as they will make the drug test results cluttered and oversized
['weed'] = {
label = 'Marijuana'
},
['oxycodone'] = {
label = 'Oxycodone',
},
['ecstacy'] = {
label = "Ecstacy",
},
['cocaine'] = {
label = 'Cocaine',
},
['meth'] = {
label = 'Methamphetamine',
},
},
EventTriggers = {
--[1] = {event = 'consumables:server:useMeth', type = 'server', drugType = 'meth', positiveTime = 4},
--[2] = {event = 'evidence:client:SetStatus', type = 'client', drugType = 'weed', drugArgPos = 1, drugArgSubfield = nil, drugArgValue = 'weedsmell'}, -- this is how you could trigger weed in QBSR
[1] = { -- event trigger for jim-consumables
event = 'jim-consumables:server:toggleItem',
drugArgPos = 2,
drugArgValue = { -- add additional drug items here
['joint'] = 'weed',
['cokebaggy'] = 'cocaine',
['crackbaggy'] = 'cocaine',
['xtcbaggy'] = 'ecstacy',
['oxy'] = 'oxycodone',
['meth'] = 'meth',
}
},
}
}

Here we can see the Config.Breathalyzer table found in r14-evidence and a brief explanation of how it works. By default, support for ESX and qb-smallresources are included out of the box to handle increasing BAC using the evidence:client:setstatus event for qb-core and the esx:setStatus event for ESX which can be used to apply the drunk status. If we have a third-party script that does not already include support for either of these methods, and it is open-source, we can create a configuration for the breathalyzer subsystem to be triggered when alochol items are used. To use the script in this way, lets go ahead an find an example script to use to set up a configuration, in this case lets use boii-consumables from https://github.com/boiidevelopment/boii-consumables-qb to set up support for it. It is open-source, and will allow us to examine the code for events we can use.

Integrating A Third Party Script

caution

Never make changes to ANY script without making a backup first, you never know what might happen!

If you have added additional drugs in qb-smallresources, or perhaps use an entirely different script for drug items, you can add support for drug testing in r14-evidence simply by adding a server event trigger at some point in your drug item code. To better understand how to add these events, we can take a look at the code used to integrate r14-evidence with qb-smallresources. We'll start with the client-side event handler that is triggered when a player smokes weed in order to apply a status effect.

Client-side Network Event Handler
RegisterNetEvent('evidence:client:SetStatus', function(statusId, time, abv)
if Config.Breathalyzer and (statusId == 'alcohol' or statusId == 'heavyalcohol') then
TriggerServerEvent('evidence:server:IncreaseBAC', abv or 15) -- increases BAC by .015 or by abv if a third argument is supplied
end

if Config.DrugTesting.Enabled and Config.DrugTesting.UsingQBSR and statusId == 'weedsmell' then
TriggerServerEvent('evidence:server:SetDrugStatus', {drug = 'weed'})
end

if time > 0 and Config.StatusList[statusId] then
if (CurrentStatusList == nil or CurrentStatusList[statusId] == nil) or (CurrentStatusList[statusId] and CurrentStatusList[statusId].time < 20) then
CurrentStatusList[statusId] = {
text = Config.StatusList[statusId],
time = time
}
Config.Functions.Notify(''..CurrentStatusList[statusId].text..'')
end
elseif Config.StatusList[statusId] then
CurrentStatusList[statusId] = nil
end
TriggerServerEvent('evidence:server:UpdateStatus', CurrentStatusList)
end)

Similiar to the breathalzyer integration, our client-side event handler is triggered when a player completes the progress bar after using a joint item, meaning that is an effective time to set the drug usage in r14-evidence. By simply adding a conditional statement here, we check if the status effect is 'weedsmell' and then trigger the 'evidence:server:SetDrugStatus' event. We create table containing the drug subfield which equals the name of the drug from our config, in this case 'weed' and that is it! There are a few ways we can trigger this event as seen below:

Triggering the Drug Status Network Event
TriggerServerEvent('evidence:server:SetDrugStatus', {drug = 'cocaine'})

TriggerEvent('evidence:server:SetDrugStatus', {cid= GetPlayerData(source).citizenid, drug = 'weed'})

Here we can see the first trigger is the same as in our above example, we simply supply a table with the drug name that we want the player to test positive for and then the server-side event handler will automatically grab the player's citizen ID. If we want to trigger this from the server, we can also do so by adding a cid' field to our argument data table. As an example of how to use these events in a script, lets look at qb-small resources and check how it handles the oxy item!

qb-smallresources Server-side CreateUseableItem()
QBCore.Functions.CreateUseableItem("oxy", function(source)
TriggerClientEvent("consumables:client:oxy", source)
end)

In this function, we can see that when the oxy item is used that it triggers a client event. This would not be an appropriate place to add our drug test status event trigger as it would automatically set a player as positive even if they canceled using it! Instead, lets follow this code to the client-side and see if there is a better place to put it!

qb-smallresources Client-side Networked Event Handler
RegisterNetEvent('consumables:client:oxy', function()
QBCore.Functions.Progressbar("use_oxy", "Healing", 2000, false, true, {
disableMovement = false,
disableCarMovement = false,
disableMouse = false,
disableCombat = true,
}, {
animDict = "mp_suicide",
anim = "pill",
flags = 49,
}, {}, {}, function() -- Done
StopAnimTask(PlayerPedId(), "mp_suicide", "pill", 1.0)
TriggerServerEvent("consumables:server:useOxy")
TriggerEvent("inventory:client:ItemBox", QBCore.Shared.Items["oxy"], "remove")
ClearPedBloodDamage(PlayerPedId())
HealOxy()
end, function() -- Cancel
StopAnimTask(PlayerPedId(), "mp_suicide", "pill", 1.0)
QBCore.Functions.Notify("Canceled", "error")
end)
end)

In this client-side code, we can see that using the 'oxy' item starts a progress bar which the player can cancel, or allow to complete in order to use the drug. In this part of the progress bar completion function would be a perfect place to trigger our server event. Let's go and place the TriggerServerEvent() function we need to trigger r14-evidence to set a player positive for the 'oxycodone' drug in our config:

Modified qb-smallresources Client-side Networked Event Handler
RegisterNetEvent('consumables:client:oxy', function()
QBCore.Functions.Progressbar("use_oxy", "Healing", 2000, false, true, {
disableMovement = false,
disableCarMovement = false,
disableMouse = false,
disableCombat = true,
}, {
animDict = "mp_suicide",
anim = "pill",
flags = 49,
}, {}, {}, function() -- Done
StopAnimTask(PlayerPedId(), "mp_suicide", "pill", 1.0)
TriggerServerEvent('evidence:server:SetDrugStatus', {drug = 'oxycodone'})
TriggerServerEvent("consumables:server:useOxy")
TriggerEvent("inventory:client:ItemBox", QBCore.Shared.Items["oxy"], "remove")
ClearPedBloodDamage(PlayerPedId())
HealOxy()
end, function() -- Cancel
StopAnimTask(PlayerPedId(), "mp_suicide", "pill", 1.0)
QBCore.Functions.Notify("Canceled", "error")
end)
end)

Here we can see that we have added our event trigger, and now when a player uses the 'oxy' item, r14-evidence will receive this information and automatically set the player's character as positive for the 'oxycodone' drug listed in our drug config. While this is a perfectly acceptable place to put this event, if this was a different script, where this effect was handled entirely on the server, we may want to find a place on the server-side code to place our event trigger. Let's follow this code to the server and see if there is an acceptable place for it!

qb-smallresources Server-side Networked Event Handler
RegisterNetEvent('consumables:server:useOxy', function()
local Player = QBCore.Functions.GetPlayer(source)

if not Player then return end

Player.Functions.RemoveItem('oxy', 1)
end)

In this event handler, we can see that the client triggers this server event to remove the used item from the player inventory. Since this is only triggered upon successful use of the 'oxy' item this is a perfect place to put our event trigger for r14-evidence. However, this time, since we are triggering a server event from the server, we must specify the citizen ID of the player's character as well since the script does not have a source to use to find it.

Modified qb-smallresources Server-side Networked Event Handler
RegisterNetEvent('consumables:server:useOxy', function()
local Player = QBCore.Functions.GetPlayer(source)

if not Player then return end

TriggerEvent('evidence:server:SetDrugStatus', {cid= Player.PlayerData.citizenid, drug = 'oxycodone'})

Player.Functions.RemoveItem('oxy', 1)
end)

We can see that the script already runs QBCore.Functions.GetPlayer() and stores the player's information in the Player variable. It checks to make sure that it actually found a player as well, and we can place our event trigger below this so it is only triggered if Player has a value preventing a potential error where we attempt to index a nil value. We then specify our drug as 'oxycodone' to match our config, and that is it! You can use this same logic to modify any script yout have access to the code for, but if your consumables or drug script is escrowed, you need to reach out to the dev responsible for it!