chore(repo): Initial commit

This commit is contained in:
Jérémie N'gadi
2017-09-19 10:29:42 +02:00
commit 92d76ed67c
14 changed files with 1248 additions and 0 deletions
+22
View File
@@ -0,0 +1,22 @@
# esx_dmvschool
FXServer ESX DMV SChool
[INSTALLATION]
1) Using [fvm](https://github.com/qlaffont/fvm-installer)
```
fvm install --save --folder=esx esx-org/esx_dmvschool
```
2) Manually
- Download https://github.com/ESX-Org/esx_dmvschool/releases/latest
- Put it in [esx] directory
1) Import esx_dmvschool.sql in your database
2) Add this in your server.cfg :
```
start esx_dmvschool
```
+27
View File
@@ -0,0 +1,27 @@
resource_manifest_version '44febabe-d386-4d18-afbe-5e627f4af937'
description 'ESX DMV School'
version '1.0.0'
server_scripts {
'server/main.lua'
}
client_scripts {
'config.lua',
'client/main.lua'
}
ui_page 'html/ui.html'
files {
'html/ui.html',
'html/logo.png',
'html/dmv.png',
'html/cursor.png',
'html/styles.css',
'html/questions.js',
'html/scripts.js',
'html/debounce.min.js'
}
+454
View File
@@ -0,0 +1,454 @@
local Keys = {
["ESC"] = 322, ["F1"] = 288, ["F2"] = 289, ["F3"] = 170, ["F5"] = 166, ["F6"] = 167, ["F7"] = 168, ["F8"] = 169, ["F9"] = 56, ["F10"] = 57,
["~"] = 243, ["1"] = 157, ["2"] = 158, ["3"] = 160, ["4"] = 164, ["5"] = 165, ["6"] = 159, ["7"] = 161, ["8"] = 162, ["9"] = 163, ["-"] = 84, ["="] = 83, ["BACKSPACE"] = 177,
["TAB"] = 37, ["Q"] = 44, ["W"] = 32, ["E"] = 38, ["R"] = 45, ["T"] = 245, ["Y"] = 246, ["U"] = 303, ["P"] = 199, ["["] = 39, ["]"] = 40, ["ENTER"] = 18,
["CAPS"] = 137, ["A"] = 34, ["S"] = 8, ["D"] = 9, ["F"] = 23, ["G"] = 47, ["H"] = 74, ["K"] = 311, ["L"] = 182,
["LEFTSHIFT"] = 21, ["Z"] = 20, ["X"] = 73, ["C"] = 26, ["V"] = 0, ["B"] = 29, ["N"] = 249, ["M"] = 244, [","] = 82, ["."] = 81,
["LEFTCTRL"] = 36, ["LEFTALT"] = 19, ["SPACE"] = 22, ["RIGHTCTRL"] = 70,
["HOME"] = 213, ["PAGEUP"] = 10, ["PAGEDOWN"] = 11, ["DELETE"] = 178,
["LEFT"] = 174, ["RIGHT"] = 175, ["TOP"] = 27, ["DOWN"] = 173,
["NENTER"] = 201, ["N4"] = 108, ["N5"] = 60, ["N6"] = 107, ["N+"] = 96, ["N-"] = 97, ["N7"] = 117, ["N8"] = 61, ["N9"] = 118
}
ESX = nil
local CurrentAction = nil
local CurrentActionMsg = nil
local CurrentActionData = nil
local Licenses = {}
local CurrentTest = nil
local CurrentTestType = nil
local CurrentVehicle = nil
local CurrentCheckPoint = 0
local LastCheckPoint = -1
local CurrentBlip = nil
local CurrentZoneType = nil
local DriveErrors = 0
local IsAboveSpeedLimit = false
local LastVehicleHealth = nil
Citizen.CreateThread(function()
while ESX == nil do
TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)
Citizen.Wait(0)
end
end)
function DrawMissionText(msg, time)
ClearPrints()
SetTextEntry_2('STRING')
AddTextComponentString(msg)
DrawSubtitleTimed(time, 1)
end
function StartTheoryTest()
CurrentTest = 'theory'
SendNUIMessage({
openQuestion = true
})
ESX.SetTimeout(200, function()
SetNuiFocus(true, true)
end)
TriggerServerEvent('esx_dmvschool:pay', Config.Prices['dmv'])
end
function StopTheoryTest(success)
CurrentTest = nil
SendNUIMessage({
openQuestion = false
})
SetNuiFocus(false)
if success then
TriggerServerEvent('esx_dmvschool:addLicense', 'dmv')
ESX.ShowNotification('Vous avez ~g~réussi~s~ le test')
else
ESX.ShowNotification('Vous avez ~r~raté~s~ le test')
end
end
function StartDriveTest(type)
ESX.Game.SpawnVehicle(Config.VehicleModels[type], Config.Zones.VehicleSpawnPoint.Pos, 317.0, function(vehicle)
CurrentTest = 'drive'
CurrentTestType = type
CurrentCheckPoint = 0
LastCheckPoint = -1
CurrentZoneType = 'residence'
DriveErrors = 0
IsAboveSpeedLimit = false
CurrentVehicle = vehicle
LastVehicleHealth = GetEntityHealth(vehicle)
local playerPed = GetPlayerPed(-1)
TaskWarpPedIntoVehicle(playerPed, vehicle, -1)
end)
TriggerServerEvent('esx_dmvschool:pay', Config.Prices[type])
end
function StopDriveTest(success)
if success then
TriggerServerEvent('esx_dmvschool:addLicense', CurrentTestType)
ESX.ShowNotification('Vous avez ~g~réussi~s~ le test')
else
ESX.ShowNotification('Vous avez ~r~raté~s~ le test')
end
CurrentTest = nil
CurrentTestType = nil
end
function SetCurrentZoneType(type)
CurrentZoneType = type
end
function OpenDMVSchoolMenu()
local ownedLicenses = {}
for i=1, #Licenses, 1 do
ownedLicenses[Licenses[i].type] = true
end
local elements = {}
if not ownedLicenses['dmv'] then
table.insert(elements, {label = 'Examen du code $' .. Config.Prices['dmv'], value = 'theory_test'})
end
if ownedLicenses['dmv'] then
if not ownedLicenses['drive'] then
table.insert(elements, {label = 'Examen de conduite [voiture] $' .. Config.Prices['drive'], value = 'drive_test', type = 'drive'})
end
if not ownedLicenses['drive_bike'] then
table.insert(elements, {label = 'Examen de conduite [moto] $' .. Config.Prices['drive_bike'], value = 'drive_test', type = 'drive_bike'})
end
if not ownedLicenses['drive_truck'] then
table.insert(elements, {label = 'Examen de conduite [camion] $' .. Config.Prices['drive_truck'], value = 'drive_test', type = 'drive_truck'})
end
end
ESX.UI.Menu.CloseAll()
ESX.UI.Menu.Open(
'default', GetCurrentResourceName(), 'dmvschool_actions',
{
title = 'Ecole de conduite',
elements = elements
},
function(data, menu)
if data.current.value == 'theory_test' then
menu.close()
StartTheoryTest()
end
if data.current.value == 'drive_test' then
menu.close()
StartDriveTest(data.current.type)
end
end,
function(data, menu)
menu.close()
CurrentAction = 'dmvschool_menu'
CurrentActionMsg = 'Appuyez sur ~INPUT_CONTEXT~ pour ouvrir le menu'
CurrentActionData = {}
end
)
end
RegisterNUICallback('question', function(data, cb)
SendNUIMessage({
openSection = 'question'
})
cb('OK')
end)
RegisterNUICallback('close', function(data, cb)
StopTheoryTest(true)
cb('OK')
end)
RegisterNUICallback('kick', function(data, cb)
StopTheoryTest(false)
cb('OK')
end)
AddEventHandler('esx_dmvschool:hasEnteredMarker', function(zone)
if zone == 'DMVSchool' then
CurrentAction = 'dmvschool_menu'
CurrentActionMsg = 'Appuyez sur ~INPUT_CONTEXT~ pour ouvrir le menu'
CurrentActionData = {}
end
end)
AddEventHandler('esx_dmvschool:hasExitedMarker', function(zone)
CurrentAction = nil
ESX.UI.Menu.CloseAll()
end)
RegisterNetEvent('esx_dmvschool:loadLicenses')
AddEventHandler('esx_dmvschool:loadLicenses', function(licenses)
Licenses = licenses
end)
-- Create Blips
Citizen.CreateThread(function()
local blip = AddBlipForCoord(Config.Zones.DMVSchool.Pos.x, Config.Zones.DMVSchool.Pos.y, Config.Zones.DMVSchool.Pos.z)
SetBlipSprite (blip, 408)
SetBlipDisplay(blip, 4)
SetBlipScale (blip, 1.2)
SetBlipAsShortRange(blip, true)
BeginTextCommandSetBlipName("STRING")
AddTextComponentString("Auto-école")
EndTextCommandSetBlipName(blip)
end)
-- Display markers
Citizen.CreateThread(function()
while true do
Citizen.Wait(0)
local coords = GetEntityCoords(GetPlayerPed(-1))
for k,v in pairs(Config.Zones) do
if(v.Type ~= -1 and GetDistanceBetweenCoords(coords, v.Pos.x, v.Pos.y, v.Pos.z, true) < Config.DrawDistance) then
DrawMarker(v.Type, v.Pos.x, v.Pos.y, v.Pos.z, 0.0, 0.0, 0.0, 0, 0.0, 0.0, v.Size.x, v.Size.y, v.Size.z, v.Color.r, v.Color.g, v.Color.b, 100, false, true, 2, false, false, false, false)
end
end
end
end)
-- Enter / Exit marker events
Citizen.CreateThread(function()
while true do
Citizen.Wait(0)
local coords = GetEntityCoords(GetPlayerPed(-1))
local isInMarker = false
local currentZone = nil
for k,v in pairs(Config.Zones) do
if(GetDistanceBetweenCoords(coords, v.Pos.x, v.Pos.y, v.Pos.z, true) < v.Size.x) then
isInMarker = true
currentZone = k
end
end
if (isInMarker and not HasAlreadyEnteredMarker) or (isInMarker and LastZone ~= currentZone) then
HasAlreadyEnteredMarker = true
LastZone = currentZone
TriggerEvent('esx_dmvschool:hasEnteredMarker', currentZone)
end
if not isInMarker and HasAlreadyEnteredMarker then
HasAlreadyEnteredMarker = false
TriggerEvent('esx_dmvschool:hasExitedMarker', LastZone)
end
end
end)
-- Block UI
Citizen.CreateThread(function()
while true do
Citizen.Wait(0)
if CurrentTest == 'theory' then
local playerPed = GetPlayerPed(-1)
DisableControlAction(0, 1, true) -- LookLeftRight
DisableControlAction(0, 2, true) -- LookUpDown
DisablePlayerFiring(playerPed, true) -- Disable weapon firing
DisableControlAction(0, 142, true) -- MeleeAttackAlternate
DisableControlAction(0, 106, true) -- VehicleMouseControlOverride
end
end
end)
-- Key Controls
Citizen.CreateThread(function()
while true do
Citizen.Wait(0)
if CurrentAction ~= nil then
SetTextComponentFormat('STRING')
AddTextComponentString(CurrentActionMsg)
DisplayHelpTextFromStringLabel(0, 0, 1, -1)
if IsControlJustReleased(0, Keys['E']) then
if CurrentAction == 'dmvschool_menu' then
OpenDMVSchoolMenu()
end
CurrentAction = nil
end
end
end
end)
-- Drive test
Citizen.CreateThread(function()
while true do
Citizen.Wait(0)
if CurrentTest == 'drive' then
local playerPed = GetPlayerPed(-1)
local coords = GetEntityCoords(playerPed)
local nextCheckPoint = CurrentCheckPoint + 1
if Config.CheckPoints[nextCheckPoint] == nil then
if DoesBlipExist(CurrentBlip) then
RemoveBlip(CurrentBlip)
end
CurrentTest = nil
ESX.ShowNotification('Test de conduite terminé')
if DriveErrors < Config.MaxErrors then
StopDriveTest(true)
else
StopDriveTest(false)
end
else
if CurrentCheckPoint ~= LastCheckPoint then
if DoesBlipExist(CurrentBlip) then
RemoveBlip(CurrentBlip)
end
CurrentBlip = AddBlipForCoord(Config.CheckPoints[nextCheckPoint].Pos.x, Config.CheckPoints[nextCheckPoint].Pos.y, Config.CheckPoints[nextCheckPoint].Pos.z)
SetBlipRoute(CurrentBlip, 1)
LastCheckPoint = CurrentCheckPoint
end
local distance = GetDistanceBetweenCoords(coords, Config.CheckPoints[nextCheckPoint].Pos.x, Config.CheckPoints[nextCheckPoint].Pos.y, Config.CheckPoints[nextCheckPoint].Pos.z, true)
if distance <= 100.0 then
DrawMarker(1, Config.CheckPoints[nextCheckPoint].Pos.x, Config.CheckPoints[nextCheckPoint].Pos.y, Config.CheckPoints[nextCheckPoint].Pos.z, 0.0, 0.0, 0.0, 0, 0.0, 0.0, 1.5, 1.5, 1.5, 102, 204, 102, 100, false, true, 2, false, false, false, false)
end
if distance <= 3.0 then
Config.CheckPoints[nextCheckPoint].Action(playerPed, CurrentVehicle, SetCurrentZoneType)
CurrentCheckPoint = CurrentCheckPoint + 1
end
end
end
end
end)
-- Speed / Damage control
Citizen.CreateThread(function()
while true do
Citizen.Wait(0)
if CurrentTest == 'drive' then
local playerPed = GetPlayerPed(-1)
if IsPedInAnyVehicle(playerPed, false) then
local vehicle = GetVehiclePedIsIn(playerPed, false)
local speed = GetEntitySpeed(vehicle) * Config.SpeedMultiplier
local tooMuchSpeed = false
for k,v in pairs(Config.SpeedLimits) do
if CurrentZoneType == k and speed > v then
tooMuchSpeed = true
if not IsAboveSpeedLimit then
DriveErrors = DriveErrors + 1
IsAboveSpeedLimit = true
ESX.ShowNotification('Vous roulez trop vite, vitesse limite : ~y~' .. v .. 'km/h')
ESX.ShowNotification('Erreurs : ~r~' .. DriveErrors .. '~s~/' .. Config.MaxErrors)
end
end
end
if not tooMuchSpeed then
IsAboveSpeedLimit = false
end
local health = GetEntityHealth(vehicle)
if health < LastVehicleHealth then
DriveErrors = DriveErrors + 1
ESX.ShowNotification('Vous avez endommagé votre véhicule')
ESX.ShowNotification('Erreurs : ~r~' .. DriveErrors .. '~s~/' .. Config.MaxErrors)
LastVehicleHealth = health
end
end
end
end
end)
+187
View File
@@ -0,0 +1,187 @@
Config = {}
Config.DrawDistance = 100.0
Config.MaxErrors = 5
Config.SpeedMultiplier = 3.6
Config.Prices = {
dmv = 200,
drive = 500,
drive_bike = 500,
drive_truck = 500
}
Config.VehicleModels = {
drive = 'blista',
drive_bike = 'sanchez',
drive_truck = 'mule3'
}
Config.SpeedLimits = {
residence = 50,
town = 80,
freeway = 120
}
Config.Zones = {
DMVSchool = {
Pos = {x = 239.471, y = -1380.960, z = 32.741},
Size = {x = 1.5, y = 1.5, z = 1.0},
Color = {r = 204, g = 204, b = 0},
Type = 1
},
VehicleSpawnPoint = {
Pos = {x = 249.409, y = -1407.230, z = 30.4094},
Size = {x = 1.5, y = 1.5, z = 1.0},
Color = {r = 204, g = 204, b = 0},
Type = -1
},
}
Config.CheckPoints = {
{
Pos = {x = 255.139, y = -1400.731, z = 29.537},
Action = function(playerPed, vehicle, setCurrentZoneType)
DrawMissionText('Allez vers le prochain passage ! Vitesse limite : ~y~' .. Config.SpeedLimits['residence'] .. 'km/h', 5000)
end
},
{
Pos = {x = 271.874, y = -1370.574, z = 30.932},
Action = function(playerPed, vehicle, setCurrentZoneType)
DrawMissionText('Allez vers le prochain passage !', 5000)
end
},
{
Pos = {x = 234.907, y = -1345.385, z = 29.542},
Action = function(playerPed, vehicle, setCurrentZoneType)
Citizen.CreateThread(function()
DrawMissionText('Faite rapidement un ~r~stop~s~ pour le piéton qui ~y~traverse', 5000)
PlaySound(-1, 'RACE_PLACED', 'HUD_AWARDS', 0, 0, 1)
FreezeEntityPosition(vehicle, true)
Citizen.Wait(4000)
FreezeEntityPosition(vehicle, false)
DrawMissionText('~g~Bien!~s~ continuons!', 5000)
end)
end
},
{
Pos = {x = 217.821, y = -1410.520, z = 28.292},
Action = function(playerPed, vehicle, setCurrentZoneType)
setCurrentZoneType('town')
Citizen.CreateThread(function()
DrawMissionText('Marquer rapidement un ~r~stop~s~ et regardez à votre ~y~gauche~s~. Vitesse limite : ~y~' .. Config.SpeedLimits['town'] .. 'km/h', 5000)
PlaySound(-1, 'RACE_PLACED', 'HUD_AWARDS', 0, 0, 1)
FreezeEntityPosition(vehicle, true)
Citizen.Wait(6000)
FreezeEntityPosition(vehicle, false)
DrawMissionText('~g~bien!~s~ prenez à ~y~droite~s~ et suivez votre file', 5000)
end)
end
},
{
Pos = {x = 178.550, y = -1401.755, z = 27.725},
Action = function(playerPed, vehicle, setCurrentZoneType)
DrawMissionText('Observez le traffic ~y~allumez vos feux~s~ !', 5000)
end
},
{
Pos = {x = 113.160, y = -1365.276, z = 27.725},
Action = function(playerPed, vehicle, setCurrentZoneType)
DrawMissionText('Allez vers le prochain passage !', 5000)
end
},
{
Pos = {x = -73.542, y = -1364.335, z = 27.789},
Action = function(playerPed, vehicle, setCurrentZoneType)
DrawMissionText('Marquez le stop pour laisser passer les véhicules !', 5000)
PlaySound(-1, 'RACE_PLACED', 'HUD_AWARDS', 0, 0, 1)
FreezeEntityPosition(vehicle, true)
Citizen.Wait(6000)
FreezeEntityPosition(vehicle, false)
end
},
{
Pos = {x = -355.143, y = -1420.282, z = 27.868},
Action = function(playerPed, vehicle, setCurrentZoneType)
DrawMissionText('Allez vers le prochain passage !', 5000)
end
},
{
Pos = {x = -439.148, y = -1417.100, z = 27.704},
Action = function(playerPed, vehicle, setCurrentZoneType)
DrawMissionText('Allez vers le prochain passage !', 5000)
end
},
{
Pos = {x = -453.790, y = -1444.726, z = 27.665},
Action = function(playerPed, vehicle, setCurrentZoneType)
setCurrentZoneType('freeway')
DrawMissionText('Il est temps d\'aller sur la rocade ! Vitesse limite : ~y~' .. Config.SpeedLimits['freeway'] .. 'km/h', 5000)
PlaySound(-1, 'RACE_PLACED', 'HUD_AWARDS', 0, 0, 1)
end
},
{
Pos = {x = -463.237, y = -1592.178, z = 37.519},
Action = function(playerPed, vehicle, setCurrentZoneType)
DrawMissionText('Allez vers le prochain passage !', 5000)
end
},
{
Pos = {x = -900.647, y = -1986.28, z = 26.109},
Action = function(playerPed, vehicle, setCurrentZoneType)
DrawMissionText('Allez vers le prochain passage !', 5000)
end
},
{
Pos = {x = 1225.759, y = -1948.792, z = 38.718},
Action = function(playerPed, vehicle, setCurrentZoneType)
DrawMissionText('Allez vers le prochain passage !', 5000)
end
},
{
Pos = {x = 1225.759, y = -1948.792, z = 38.718},
Action = function(playerPed, vehicle, setCurrentZoneType)
setCurrentZoneType('town')
DrawMissionText('Entrée en ville, attention à votre vitesse ! Vitesse limite : ~y~' .. Config.SpeedLimits['town'] .. 'km/h', 5000)
end
},
{
Pos = {x = 1163.603, y = -1841.771, z = 35.679},
Action = function(playerPed, vehicle, setCurrentZoneType)
DrawMissionText('Bravo, restez vigilant!', 5000)
PlaySound(-1, 'RACE_PLACED', 'HUD_AWARDS', 0, 0, 1)
end
},
{
Pos = {x = 235.283, y = -1398.329, z = 28.921},
Action = function(playerPed, vehicle, setCurrentZoneType)
ESX.Game.DeleteVehicle(vehicle)
end
},
}
+7
View File
@@ -0,0 +1,7 @@
USE `essentialmode`;
INSERT INTO `licenses` (`type`, `label`) VALUES
('drive', 'Permis de conduire'),
('drive_bike', 'Permis moto'),
('drive_truck', 'Permis camion')
;
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

+9
View File
@@ -0,0 +1,9 @@
/*
* jQuery throttle / debounce - v1.1 - 3/7/2010
* http://benalman.com/projects/jquery-throttle-debounce-plugin/
*
* Copyright (c) 2010 "Cowboy" Ben Alman
* Dual licensed under the MIT and GPL licenses.
* http://benalman.com/about/license/
*/
(function(b,c){var $=b.jQuery||b.Cowboy||(b.Cowboy={}),a;$.throttle=a=function(e,f,j,i){var h,d=0;if(typeof f!=="boolean"){i=j;j=f;f=c}function g(){var o=this,m=+new Date()-d,n=arguments;function l(){d=+new Date();j.apply(o,n)}function k(){h=c}if(i&&!h){l()}h&&clearTimeout(h);if(i===c&&m>e){l()}else{if(f!==true){h=setTimeout(i?k:l,i===c?e-m:e)}}}if($.guid){g.guid=j.guid=j.guid||$.guid++}return g};$.debounce=function(d,e,f){return f===c?a(d,e,false):a(d,f,e!==false)}})(this);
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 745 B

+71
View File
@@ -0,0 +1,71 @@
var tableauQuestion = [
{ question : "Si vous conduisez à 80km/h, que vous approchez d'un lieu de résidence, cela veut dire que :",
propositionA : "Vous devez accélérer",
propositionB : "Vous pouvez garder votre vitesse, si vous ne croisez pas d'autres véhicules",
propositionC : "Vous devez ralentir",
propositionD : "Vous pouvez garder votre vitesse",
reponse : "C"},
{ question : "Vous vous apprétez à tourner à droite au feu vert, mais vous voyez un piéton qui traverse :",
propositionA : "Vous passez avant le piéton",
propositionB : "Vous vérifiez qu'il n'y a pas d'autre véhicule et vous passez",
propositionC : "Vous attendez que le piéton est terminé",
propositionD : "Vous shoutez le piéton pour passer",
reponse : "C"},
{ question : "Sans aucune indication : La vitesse dans une zone résidentielle est de : __ km/h",
propositionA : "50",
propositionB : "55",
propositionC : "65",
propositionD : "70",
reponse : "A"},
{ question : "Avant chaque changement de file vous devez :",
propositionA : "Vérifiez vos rétroviseurs",
propositionB : "Vérifiez vos angles morts",
propositionC : "Signalez vos intentions",
propositionD : "Tout cela",
reponse : "D"},
{ question : "What blood alcohol level is classified as driving while intoxicated?",
propositionA : "0.05%",
propositionB : "0.18%",
propositionC : "0.08%",
propositionD : "0.06%",
reponse : "C"},
{ question : "A quel moment vous pouvez passer aux feux ?",
propositionA : "Quand il est vert",
propositionB : "Quand il n'y a personne sur l'intersection",
propositionC : "Vous êtes dans une zone d'école",
propositionD : "Quand il est vert et/ou rouge et que je tourne à droite",
reponse : "D"},
{ question : "Un piéton est au feu rouge pour les piétons",
propositionA : "Vous le laissez passer",
propositionB : "Vous observez avant de continuer",
propositionC : "Vous lui faite un signe de la main",
propositionD : "Vous continuez votre chemin car votre feu est vert",
reponse : "D"},
{ question : "Qu'est ce qui est permit quand vous dépassez un autre véhicule",
propositionA : "Le suivre de près pour le doubler plus vite",
propositionB : "Le doubler en quittant la route",
propositionC : "Conduire sur la route opposé pour le dépasser",
propositionD : "Dépasser la vitesse limite",
reponse : "C"},
{ question : "Vous conduisez sur une rocade qui indique une vitesse maximum de 110 km/h. La plupart du traffic roule à 120 km/h, alors vous ne devriez pas conduire plus vite que :",
propositionA : "80 kmh",
propositionB : "40 kmh",
propositionC : "50 kmh",
propositionD : "110 kmh",
reponse : "D"},
{ question : "Quand vous êtes dépassé par un autre véhicule il est important de ne PAS :",
propositionA : "Ralentir",
propositionB : "Vérifiez vos rétroviseurs",
propositionC : "Regarder les autres conducteurs",
propositionD : "Augmenter votre vitesse",
reponse : "D"},
]
+144
View File
@@ -0,0 +1,144 @@
// Mouse Controls
var documentWidth = document.documentElement.clientWidth;
var documentHeight = document.documentElement.clientHeight;
var cursor = $('#cursor');
var cursorX = documentWidth / 2;
var cursorY = documentHeight / 2;
//question variables
var questionNumber = 1;
var userAnswer = [];
var goodAnswer = [];
var questionUsed = [];
var nbQuestionToAnswer = 10; // don't forget to change the progress bar max value in html
var nbAnswerNeeded = 1; // out of nbQuestionToAnswer
var nbPossibleQuestions = 10; //number of questions in database questions.js
var lastClick = 0;
/*
var nbQuestionToAnswer = 10; // don't forget to change the progress bar max value in html
var nbAnswerNeeded = 8; // out of nbQuestionToAnswer
var nbPossibleQuestions = 15; //number of questions in database questions.js
*/
function getRandomQuestion() {
var continuer = true;
var random;
while (continuer){
continuer=false; // do not continue loop
random = Math.floor(Math.random() * nbPossibleQuestions) ; // number of possible questions
if(questionNumber==1){
return random;
}
for(i=0; i<questionNumber-1; i++){
if (random == questionUsed[i]) {
continuer=true; // continue loop only if random is already used
}
}
}
questionUsed.push(random);
return random;
}
// Partial Functions
function closeMain() {
$(".home").css("display", "none");
}
function openMain() {
$(".home").css("display", "block");
}
function closeAll() {
$(".body").css("display", "none");
}
function openQuestionnaire() {
$(".questionnaire-container").css("display", "block");
var randomQuestion = getRandomQuestion();
$("#questionNumero").html("Question : " + questionNumber);
$("#question").html(tableauQuestion[randomQuestion].question);
$(".answerA").html(tableauQuestion[randomQuestion].propositionA);
$(".answerB").html(tableauQuestion[randomQuestion].propositionB);
$(".answerC").html(tableauQuestion[randomQuestion].propositionC);
$(".answerD").html(tableauQuestion[randomQuestion].propositionD);
$('input[name=question]').attr('checked',false);
goodAnswer.push(tableauQuestion[randomQuestion].reponse);
$(".questionnaire-container .progression").val(questionNumber-1);
}
function openResultGood() {
$(".resultGood").css("display", "block");
}
function openResultBad() {
$(".resultBad").css("display", "block");
}
function openContainer() {
$(".question-container").css("display", "block");
$("#cursor").css("display", "block");
}
function closeContainer() {
$(".question-container").css("display", "none");
$("#cursor").css("display", "none");
}
// Listen for NUI Events
window.addEventListener('message', function(event){
var item = event.data;
// Open & Close main gang window
if(item.openQuestion == true) {
openContainer();
openMain();
}
if(item.openQuestion == false) {
closeContainer();
closeMain();
}
// Open sub-windows / partials
if(item.openSection == "question") {
closeAll();
openQuestionnaire();
}
});
// Handle Button Presses
$(".btnQuestion").click(function(){
$.post('http://esx_dmvschool/question', JSON.stringify({}));
});
$(".btnClose").click(function(){
$.post('http://esx_dmvschool/close', JSON.stringify({}));
});
$(".btnKick").click(function(){
$.post('http://esx_dmvschool/kick', JSON.stringify({}));
});
// Handle Form Submits
$("#question-form").submit(function(e) {
e.preventDefault();
if(questionNumber!=nbQuestionToAnswer){
//question 1 to 9 : pushing answer in array
closeAll();
userAnswer.push($('input[name="question"]:checked').val());
questionNumber++;
openQuestionnaire();
}
else {
// question 10 : comparing arrays and sending number of good answers
userAnswer.push($('input[name="question"]:checked').val());
var nbGoodAnswer = 0;
for (i = 0; i < nbQuestionToAnswer; i++) {
if (userAnswer[i] == goodAnswer[i]) {
nbGoodAnswer++;
}
}
closeAll();
if(nbGoodAnswer >= nbAnswerNeeded) {
openResultGood();
}
else{
openResultBad();
}
}
return false;
});
+191
View File
@@ -0,0 +1,191 @@
html {
overflow: hidden;
font-family: 'Open Sans', sans-serif;
}
#cursor {
position: absolute;
z-index: 99999999;
display: none;
}
.full-screen {
width: 100%;
height:100%;
display: flex;
align-items: center;
}
.question-container {
width: 70%;
height: 700px;
background-color: #fff;
border: 1px solid #222;
border-radius: 1px;
margin-left: auto;
margin-right: auto;
overflow: hidden;
z-index: 9999999;
display: none;
}
.header {
width:100%;
height: 20%;
background-color: #eee;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
}
.header .logo {
width: 80%;
max-height: 50%;
margin: auto;
margin-bottom: 0;
}
.header h1 {
font-size: 2em;
text-align: center;
margin:auto;
}
.body {
width: 100%;
height: 80%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
display: none;
}
.content {
display: flex;
flex-direction: column;
align-self: center;
width: 90%;
height: 70%;
margin: auto;
border:none;
}
.content .logo {
width: auto;
max-height: auto;
margin: auto;
margin-bottom: 0;
}
.content h2, p {
margin: 5px;
}
.buttonspot {
display: flex;
flex-direction: column;
align-self: center;
width: auto;
height: 15%;
margin: auto;
border:none;
}
.buttonspot h2, p {
margin: 5px;
}
.button {
width: 30%;
height: 40px;
align-self: center;
text-align: center;
margin-left: 40px;
margin-right: 40px;
background: #6699ff;
background-image: linear-gradient(to bottom, #6699ff, #4d88ff);
border-radius: 4px;
color: #ffffff;
font-size: 1.5em;
text-decoration: none;
}
.form {
display: flex;
flex-direction: row;
justify-content: center;
flex-wrap: wrap;
width: 100%;
margin-top:5px;
}
.form div {
margin :auto;
margin-top:5px;
margin-bottom: 5px;
width: 100%;
}
.submit{
align-items: center;
height: 30px;
text-align: center;
width: 30%;
background: #017ebc;
background-image: linear-gradient(to bottom, #6699ff, #4d88ff);
border-radius: 4px;
color: #fff;
font-size: 1.2em;
margin-top: 10px;
}
.barre-progression {
width: 50%;
align-self: center;
height: 10%;
margin: auto;
margin-top: 0;
display: flex;
flex-wrap: wrap;
justify-content: center;
padding: 0;
}
.barre-progression h2{
width: 100%;
height: 60%;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
margin:0;
color: #6699ff;
}
.progression {
width: 80%;
border: 0 none;
background: #ddd;
border-radius: 14px;
box-shadow: inset 0px 1px 1px rgba(0,0,0,0.5), 0px 1px 0px rgba(255,255,255,0.2);
}
.progression::-moz-progress-bar {
background: #FFF;
border-radius: 14px;
box-shadow: inset 0 -2px 4px rgba(0,0,0,0.4), 0 2px 5px 0px rgba(0,0,0,0.3);
}
.progression::-webkit-progress-bar {
background: transparent;
}
.progression::-webkit-progress-value {
background-image: linear-gradient(to bottom, #6699ff, #4d88ff);
border-radius: 14px;
box-shadow: inset 0 -2px 4px rgba(0,0,0,0.4), 0 2px 5px 0px rgba(0,0,0,0.3);
}
.bold-text{
font-weight: bold;
font-size: 1.3em;
}
+102
View File
@@ -0,0 +1,102 @@
<head>
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
<link rel="stylesheet" href="styles.css" type="text/css">
</head>
<body>
<div class="full-screen">
<div class="question-container">
<!-- header -->
<div class="header">
<h1>Auto-école</h1>
</div>
<!-- home -->
<div class="body home">
<div class="content">
<!-- ICI BREVE PRESENTATION -->
<center><img src="dmv.png" class="logo"><br><p class="bold-text">Bienvenu à votre Auto-école</center>
<br><center>Tous les citoyens de Los Santos doivent réussir leur examen de code avant de pouvoir conduire.<br>Prenez votre temps, répondez avec du bon sens, ne répondez pas au hasard.<br><br></center>
Examen de Code<br>
- L'examen de code coute 200$, cela n'est pas remboursé si vous échouez.<br>
- N'ayez pas peur, l'auto-école accepte les crédits, mais faite attention à ne pas vous endetter<br>
- Si vous loupez votre test une première fois, vous ne pouvez pas le repasser de suite, vous devrez le retenter un autre jour.<br><br>
Examen de Conduite<br>
- L'examen de Conduite coute 500$, comme pour l'examen de code, ce paiement ne vous sera pas remboursé si vous échoué.<br>
- La chose principale pour votre permis c'est de faire attention à ce qui vous entoure et surtout éviter les accidents !</p>
</div>
<div class="buttonspot">
<a href="#" class="button btnQuestion">Démarrer</a>
</div>
<div class ="barre-progression" >
<h2>Progrès</h2>
<progress class="progression" value="0" max="10" >
</div>
</div>
<!-- Question-->
<div class="body questionnaire-container">
<div class="content">
<h2 id="questionNumero"></h2>
<p id="question"></p>
<form class="form" id="question-form">
<div>
<input type="radio" name="question" id="answerA" value="A">
<label class="answerA"></label>
</div>
<div>
<input type="radio" name="question" id="answerB" value="B">
<label class="answerB"></label>
</div>
<div>
<input type="radio" name="question" id="answerC" value="C">
<label class="answerC"></label>
</div>
<div>
<input type="radio" name="question" id="answerD" value="D">
<label class="answerD"></label>
</div>
<button type="submit" id="submit" class="submit">Prochaine question</button>
</form>
</div>
<div class ="barre-progression">
<h2>Progrès</h2>
<progress class="progression" value="0" max="10" >
</div>
</div>
<!-- Résults -->
<div class="body resultGood">
<div class="content">
<center><p class="bold-text">Bon travail !</p><br><br>Vous avez bien travaillé durant l'examen!<br><br>Vous pouvez maintenant fermer cette fenètre et passer à l'examen.</center>
</div>
<div class="buttonspot">
<a href="#" class="button btnClose">Fermer</a>
</div>
<div class ="barre-progression" >
<h2>Progrès</h2>
<progress class="progression" value="10" max="10" >
</div>
</div>
<div class="body resultBad">
<div class="content">
<center><p class="bold-text">Vous avez échoué</p><br><br>Vous n'êtes pas prêt pour ce test, essayez une nouvelle fois, plus tard...<br><br></center>
</div>
<div class="buttonspot">
<a href="#" class="button btnKick">Fermer</a>
</div>
<div class ="barre-progression" >
<h2>Progrès</h2>
<progress class="progression" value="10" max="10" >
</div>
</div>
</div>
</div>
<script src="nui://game/ui/jquery.js" type="text/javascript"></script>
<script src="questions.js" type="text/javascript"></script>
<script src="scripts.js" type="text/javascript"></script>
<script src="debounce.min.js" type="text/javascript"></script>
</body>
+34
View File
@@ -0,0 +1,34 @@
ESX = nil
TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)
AddEventHandler('esx:playerLoaded', function(source)
TriggerEvent('esx_license:getLicenses', source, function(licenses)
TriggerClientEvent('esx_dmvschool:loadLicenses', source, licenses)
end)
end)
RegisterNetEvent('esx_dmvschool:addLicense')
AddEventHandler('esx_dmvschool:addLicense', function(type)
local _source = source
TriggerEvent('esx_license:addLicense', _source, type, function()
TriggerEvent('esx_license:getLicenses', _source, function(licenses)
TriggerClientEvent('esx_dmvschool:loadLicenses', _source, licenses)
end)
end)
end)
RegisterNetEvent('esx_dmvschool:pay')
AddEventHandler('esx_dmvschool:pay', function(price)
local _source = source
local xPlayer = ESX.GetPlayerFromId(_source)
xPlayer.removeMoney(price)
TriggerClientEvent('esx:showNotification', _source, 'Vous avez payé ~g~$' .. price)
end)