Configuration
Every option in STG Driving School config/config.lua, from license types, routes and road events to exam rules, the question pool and server hooks.
All settings live in stg-drivingschool/config/config.lua. The file stays editable in the escrow version, and so do the files in stg-drivingschool/locales/. Restart the resource after a change.
Language
Config.Language = 'en'Available: en, de, fr, es, pt, it, nl, pl, sv, no, fi, cs, ar, he, jp, zh. If the file is missing, the script falls back to English. To change a text, edit the matching file in stg-drivingschool/locales/. The theory questions live in the same files, see Question pool.
Interaction
Config.TargetSystem = 'auto'How players open the school menu at the instructor NPC.
| Value | Effect |
|---|---|
'auto' | Uses ox_target if it is running, then qb-target. Without either, players press E within 2.5 metres. |
'ox-target' | Always uses ox_target. |
'qb-target' | Always uses qb-target. |
false | No target, players always press E. |
Speed unit
Config.SpeedType = 'kmh''kmh' or 'mph'. Every speed limit in the config is read in this unit, the exam HUD shows it, and km/h in the locale texts and question answers is replaced with mph. The numbers themselves are not converted, so adjust the limits and question answers when you switch.
School NPC
Config.Menu = {
model = 'u_m_m_jewelsec_01',
coords = vector4(-650.24, -2243.51, 5.93, 318.0),
scenario = 'WORLD_HUMAN_CLIPBOARD',
blip = {
enabled = true,
sprite = 56,
color = 3,
scale = 0.7
}
}Prop
Type
Exam rules
Config.Exam = {
passingScore = 70,
practicalTimeLimit = 10,
penaltyCooldown = 2000,
refundOnCancel = true,
refundOnFail = true,
sharedTheory = false
}Prop
Type
The license price is charged once, in cash, when the player starts the theory exam. A passed theory exam is saved, so a player who fails the practical exam can try it again without paying or taking the theory again.
NPC camera
Config.NPCCamera = {
enabled = true,
fov = 80.0,
distance = 0.58,
height = 0.04,
freeze = false,
shake = 0.03
}When the menu opens, the camera moves to the instructor's face.
Prop
Type
License types
Each entry in Config.LicenseTypes is one card in the menu with its own exam:
Config.LicenseTypes = {
{
id = 'car',
label = Locales[Config.Language].Web.web_car_title,
description = Locales[Config.Language].Web.web_car_desc,
class = 'B',
price = 10000,
questionKey = 'car',
licenseName = 'drive_b',
image = 'b.png',
practical = {
startCoords = vector4(-609.73, -2231.21, 6.01, 48.18),
vehicleModel = 'blista',
speedLimit = 70.0,
maxPenaltyPoints = 5,
maxDistanceFromCheckpoint = 500.0,
checkpointRadius = 10.0,
animations = { ... },
checkpoints = {
vector3(-622.8, -2218.61, 6.0),
-- ...
}
}
},
-- motorcycle, truck, helicopter, plane, boat
}Prop
Type
The defaults:
| id | Class | Price | License name | Vehicle |
|---|---|---|---|---|
car | B | 10000 | drive_b | blista |
motorcycle | A | 5000 | drive_a | faggio |
truck | C E | 20000 | drive_c | phantom |
helicopter | H | 50000 | drive_h | maverick |
plane | P | 75000 | drive_plane | mammatus |
boat | S | 15000 | drive_boat | marquis |
Practical exam
Prop
Type
During the practical exam:
- Speed is checked every second. Each check above the limit adds a penalty point, at most one per
penaltyCooldown. - Damage to the vehicle body adds a penalty point.
- The player cannot leave the vehicle. If they get out, they are put back in the driver seat.
- The exam fails when the penalty points reach
maxPenaltyPoints, the time runs out, the player goes too far from the next checkpoint or the vehicle is destroyed. - When the exam ends, passed or failed, the vehicle is removed and the player is brought back to the instructor.
The helicopter, plane and boat entries also contain returnToSchool = true. It has no effect: players always return to the instructor.
The ids helicopter and plane get larger checkpoint markers that can be seen from 500 metres. Keep these ids for aircraft licenses.
Road events
animations = {
pedestrian = { checkpoint = 4, coords = vector4(-647.19, -2158.96, 5.99, 49.73) },
roadExit = { checkpoint = 8, coords = vector4(-595.17, -2045.0, 6.15, 311.89) },
speedChange = {
{ checkpoint = 9, newLimit = 120.0 },
{ checkpoint = 20, newLimit = 80.0 },
},
dog = { checkpoint = 12, coords = vector4(-154.51, -2191.0, 10.28, 18.18) },
trafficLight = 16
},checkpoint is the number of the checkpoint the player is heading to: the event plays the moment the checkpoint before it is cleared. During an event the vehicle is braked to a stop, the controls are locked and a camera shows the scene. Set checkpoint = false, or remove the line, to turn an event off.
| Event | What happens |
|---|---|
pedestrian | A pedestrian walks across the road. coords is the camera position and the pedestrian's start point, w is the camera direction. The pedestrian walks at a right angle to it. Lasts about 8 seconds. |
roadExit | The camera at coords looks left, right and left again before the player may join the road. |
speedChange | A list of { checkpoint, newLimit }. The limit changes and the player is told whether it went up or down. Add as many entries as you want. |
dog | A dog runs diagonally across the road from coords while the camera follows it. |
trafficLight | A checkpoint number, or false. The camera points at that checkpoint for 5 seconds with a warning to stop at red lights. |
Adding a license type
Copy an existing entry in Config.LicenseTypes and give it a new id and licenseName.
Set label, description, class, price and image. Plain text works for label and description.
Set questionKey to an existing question set, or add a new set with that name to the Questions table of your language file.
Set startCoords, vehicleModel and the checkpoints of the route. Drive the route once and copy your coordinates at each turn.
Question pool
The theory questions are in the locale files, under Questions. Edit the file of the language set in Config.Language, for example stg-drivingschool/locales/en.lua:
Questions = {
car = {
{
question = 'What is the maximum speed limit in the city?',
answers = {'50 km/h', '60 km/h', '70 km/h', '80 km/h'},
correct = 1
},
-- ...
},
moto = { ... },
truck = { ... },
helicopter = { ... },
plane = { ... },
boat = { ... },
}Prop
Type
Every license type ships with 12 questions. The exam asks every question in the set, so add or remove entries to make it longer or shorter. The score is the share of correct answers, compared with passingScore.
Notifications
Config.Functions = {
["helpNotify"] = function(message, icon)
lib.showTextUI(message, { position = "right-center", icon = icon, ... })
end,
["hideHelpNotify"] = function()
lib.hideTextUI()
end,
["notify"] = function(type, message)
lib.notify({ title = _('notify_title'), description = message, type = type, duration = 5000 })
end,
}- helpNotify / hideHelpNotify: the [E] Driving School prompt shown near the instructor when no target system is used.
- notify: replace the body to use your own notification system.
Exam hooks
These functions in Config.Functions let you add your own rules and rewards without touching the rest of the script.
canStartExam
["canStartExam"] = function(source, data)
return true
end,Runs on the server before an exam starts. data.licenseType is the license id and data.examType is 'theory' or 'practical'. Return true to allow the exam, or false and a message to block it. For the theory exam it runs before the fee is taken.
["canStartExam"] = function(source, data)
if data.licenseType == 'truck' and not exports['stg-drivingschool']:hasLicense(source, 'drive_b') then
return false, 'You need a car license first!'
end
return true
end,This example only lets players take the truck exams once they hold a car license. See Exports for hasLicense.
Pass hooks
["onTheoryPassed"] = function(data) end,
["onPracticalPassed"] = function(data) end,
["onTheoryPassedServer"] = function(source, data) end,
["onPracticalPassedServer"] = function(source, data) end,| Function | Side | data |
|---|---|---|
onTheoryPassed | client | { licenseType, score } |
onPracticalPassed | client | { licenseType, licenseName } |
onTheoryPassedServer | server | { licenseType, score } |
onPracticalPassedServer | server | { licenseType, licenseName } |
The license is already saved when these run. By default, onPracticalPassed refreshes the cards of stg-walletv2 and onPracticalPassedServer gives a card through cs_license when those resources are running. Put your own code next to them, for example to give an item or send a log.
Fuel and keys
["setFuel"] = function(vehicle) ... end,
["giveKeys"] = function(plate, vehicle) ... end,
["removeKeys"] = function(plate, vehicle) ... end,- setFuel: fills the exam vehicle when it spawns. Supports
stg-vanaheimfuel,ox_fuel,LegacyFuel,cdn-fuelandps-fuel, and falls back to the game's own fuel level. - giveKeys / removeKeys: give the exam vehicle's keys at the start and take them back at the end. Supports
qbx_vehiclekeys,qb-vehiclekeys,qs-vehiclekeys,wasabi_carlock,t1ger_keys,mk_vehiclekeys,cd_garage,vehicles_keys,renzu_vehiclekeysandesx_vehiclelock.
The first running resource in each list is used. For another fuel or key script, add a block for it at the top of the function.
Still having trouble?
Open a ticket on our Discord. Our team answers around 15 hours a day.