diff --git a/client/creator.lua b/client/creator.lua index 62f18af..8261a6e 100644 --- a/client/creator.lua +++ b/client/creator.lua @@ -318,6 +318,34 @@ function ListQuestions() lib.showContext(ctx.id) end +local function ListPreExamQuestions() + local ctx = { + id = "menu_pre_questions", + menu = "menu_whitelist", + title = "Perguntas pré-exame", + onExit = OnExit, + options = {} + } + + for key, question in ipairs(Config.PreExamQuestions) do + ctx.options[#ctx.options + 1] = { + title = question.question, + description = "aaa", + --string.format("Índice: %s, Opções: %s", key, #question.options or 0), + icon = "clipboard-question", + iconAnimation = Config.IconAnimation, + arrow = true, + onSelect = QuestionActionMenu, + args = { + callback = ListPreExamQuestions, + questionKey = key + } + } + end + lib.registerContext(ctx) + lib.showContext(ctx.id) +end + local function ToggleWhitelist(args) Config.Enabled = not Config.Enabled args.callback() @@ -512,6 +540,13 @@ local function ConfigWhitelist() iconAnimation = Config.IconAnimation, onSelect = ListQuestions } + -- { + -- title = "Perguntas pré-exame", + -- description = "Perguntas que serão feitas antes do exame", + -- icon = "list", + -- iconAnimation = Config.IconAnimation, + -- onSelect = ListPreExamQuestions + -- } } } lib.registerContext(ctx) diff --git a/client/main.lua b/client/main.lua index e8bcb90..22db0f2 100644 --- a/client/main.lua +++ b/client/main.lua @@ -65,6 +65,18 @@ local function beginExam() local correctAnswers = 0 local ped = PlayerPedId() if ped then + if Config["PreExamQuestions"] and Config.PreExamQuestions["Enabled"] then + local input = lib.inputDialog(Config.PreExamQuestions.label, Config.PreExamQuestions.information) + if not input then + return + end + local result = {} + for k, v in pairs(Config.PreExamQuestions.information) do + result[v.label] = {kind = v.kind, value = input[k]} + end + + lib.callback.await("mri_Qwhitelist:Server:SendPreExamData", false, result) + end if not showAlertDialog(Config.StartExamHeader, Config.StartExamContent, true, "Iniciar") then return end @@ -95,7 +107,9 @@ function loadCitizenship() if Config.Interaction.Type == "marker" then Marker:LoadInteractions({callbackFunction = beginExam}) elseif Config.Interaction.Type == "target" then - if Target.TargetId then return end + if Target.TargetId then + return + end Target:LoadInteractions({callbackFunction = beginExam}) elseif Config.Interaction.Type == "3dtext" then Text:LoadInteractions({callbackFunction = beginExam}) diff --git a/server/config.sample.lua b/server/config.sample.lua index 25bf929..f4c1055 100644 --- a/server/config.sample.lua +++ b/server/config.sample.lua @@ -2,98 +2,142 @@ Config = { Enabled = true, -- Coloque false para desativar a whitelist. Debug = false, -- Coloque true para habilitar o debug. Percent = 70, -- Porcentagem de respostas corretas para liberar o player - loadNotify = 'Você deve completar o exame de cidadania para jogar!', -- Notification when player loads in without completing citizenship. - escapeNotify = 'Você deve completar o exame de cidadania para jogar!', -- Notification when player tries to leave citizenship office. + loadNotify = "Você deve completar o exame de cidadania para jogar!", -- Notification when player loads in without completing citizenship. + escapeNotify = "Você deve completar o exame de cidadania para jogar!", -- Notification when player tries to leave citizenship office. -- Labels for Exam: - StartExamLabel = 'Iniciar o exame de cidadania', - StartExamHeader = 'Exame de cidadania', - StartExamContent = 'Todos os novos cidadãos devem passar no exame antes que possam jogar. Faça no seu tempo, responda com bom senso e não responda aleatoriamente.', - SuccessHeader = 'Você passou no exame de cidadania!', - SuccessContent = 'Bem-vindo ao nosso servidor!', - FailedHeader = 'Você falhou no exame de cidadania!', - FailedContent = 'Por favor, tente novamente.', + StartExamLabel = "Iniciar o exame de cidadania", + StartExamHeader = "Exame de cidadania", + StartExamContent = "Todos os novos cidadãos devem passar no exame antes que possam jogar. Faça no seu tempo, responda com bom senso e não responda aleatoriamente.", + SuccessHeader = "Você passou no exame de cidadania!", + SuccessContent = "Bem-vindo ao nosso servidor!", + FailedHeader = "Você falhou no exame de cidadania!", + FailedContent = "Por favor, tente novamente.", PassingScore = 4, -- Amount of value questions required to get citizenship. - NotifyType = 'ox_lib', -- Support for 'ox_lib', 'qb', 'esx', 'okok' and 'custom' to use a different type. + NotifyType = "ox_lib", -- Support for 'ox_lib', 'qb', 'esx', 'okok' and 'custom' to use a different type. Interaction = { - Type = 'target', -- Supports 'marker' and 'target' and '3dtext' - - MarkerLabel = 'Comece o exame de cidadania', + Type = "target", -- Supports 'marker' and 'target' and '3dtext' + MarkerLabel = "Comece o exame de cidadania", MarkerType = 27, -- https://docs.fivem.net/docs/game-references/markers/ - MarkerColor = { r = 26, g = 115, b = 179}, -- RGB Color picker: https://g.co/kgs/npUqed1 - MarkerSize = { x = 1.0, y = 1.0, z = 1.0}, + MarkerColor = {r = 26, g = 115, b = 179}, -- RGB Color picker: https://g.co/kgs/npUqed1 + MarkerSize = {x = 1.0, y = 1.0, z = 1.0}, MarkerOnFloor = false, - - TargetIcon = 'fas fa-passport', -- https://fontawesome.com/icons - TargetLabel = 'Comece o exame de cidadania', + TargetIcon = "fas fa-passport", -- https://fontawesome.com/icons + TargetLabel = "Comece o exame de cidadania", TargetRadius = vector3(4, 4, 4), - TargetDistance = 2.0, + TargetDistance = 2.0 }, - -- DO NOT MODIFY UNLESS YOU ARE GOING TO MODIFY citizenZone. - SpawnCoords = vec4(-66.24, -822.09, 285.61 -1, 78.8), + SpawnCoords = vec4(-66.24, -822.09, 285.61 - 1, 78.8), ExamCoords = vec3(-68.24, -814.40, 285.35), -- vec3(-1372.2820, -465.5251, 71.8305) CompletionCoords = vec4(-1042.68, -2745.97, 21.36, 323.7), - - citizenZone = { -- Can be created through /zone box + citizenZone = { + -- Can be created through /zone box coords = vec3(-73.34, -821.15, 285.0), size = vec3(28.0, 22.2, 6.2), - rotation = 340.0, + rotation = 340.0 }, - Questions = { { - question = 'O que é Meta Gaming?', + question = "O que é Meta Gaming?", options = { - {label = 'Metagaming é o uso de qualquer informação que seu personagem não aprendeu dentro do roleplay na cidade.', value = true}, - {label = 'Metagaming é quando você tenta vender pés de galinha para as pessoas e você não tem nenhum pé de galinha.', value = false}, - {label = 'Eu não sei.', value = false}, - {label = 'Metagaming é quando você não teme pela sua vida.', value = false} + { + label = "Metagaming é o uso de qualquer informação que seu personagem não aprendeu dentro do roleplay na cidade.", + value = true + }, + { + label = "Metagaming é quando você tenta vender pés de galinha para as pessoas e você não tem nenhum pé de galinha.", + value = false + }, + {label = "Eu não sei.", value = false}, + {label = "Metagaming é quando você não teme pela sua vida.", value = false} } }, { - question = 'O que é Power Gaming?', + question = "O que é Power Gaming?", options = { - {label = 'Powergaming é o uso de formas de roleplay irreais ou a recusa total de fazer roleplay para se dar uma vantagem injusta.', value = true}, - {label = 'Powergaming é o uso do cartão de crédito da sua mãe para comprar Fundador Suporte ;)', value = false}, - {label = 'Powergaming é quando você invade o clube de alguém usando exploits.', value = false}, - {label = 'Eu não sei.', value = false} + { + label = "Powergaming é o uso de formas de roleplay irreais ou a recusa total de fazer roleplay para se dar uma vantagem injusta.", + value = true + }, + { + label = "Powergaming é o uso do cartão de crédito da sua mãe para comprar Fundador Suporte ;)", + value = false + }, + {label = "Powergaming é quando você invade o clube de alguém usando exploits.", value = false}, + {label = "Eu não sei.", value = false} } }, { - question = 'Você pode usar software de trapaça de terceiros?', + question = "Você pode usar software de trapaça de terceiros?", options = { - {label = 'Isso não é permitido sob nenhuma circunstância.', value = true}, - {label = 'Sim, claro, eu adoro eulen!', value = false}, - {label = 'Somente se você pedir permissão para sua mãe.', value = false}, - {label = 'Eu não sei.', value = false} + {label = "Isso não é permitido sob nenhuma circunstância.", value = true}, + {label = "Sim, claro, eu adoro eulen!", value = false}, + {label = "Somente se você pedir permissão para sua mãe.", value = false}, + {label = "Eu não sei.", value = false} } }, { - question = 'Qual dos exemplos abaixo é uma Zona Verde?', + question = "Qual dos exemplos abaixo é uma Zona Verde?", options = { - {label = 'Hospitais.', value = true}, - {label = 'Bancos de parque.', value = false}, - {label = 'Em todos os lugares.', value = false}, - {label = 'Todos os itens acima', value = false} + {label = "Hospitais.", value = true}, + {label = "Bancos de parque.", value = false}, + {label = "Em todos os lugares.", value = false}, + {label = "Todos os itens acima", value = false} } }, { - question = 'O que significa quebrar o personagem?', + question = "O que significa quebrar o personagem?", options = { - {label = 'Quando você fala fora do personagem dentro da cidade.', value = true}, - {label = 'Quando você quebra o personagem de outro jogador.', value = false}, - {label = 'Quando seu tio não vem te buscar na escola.', value = false}, - {label = 'Eu não sei.', value = false} + {label = "Quando você fala fora do personagem dentro da cidade.", value = true}, + {label = "Quando você quebra o personagem de outro jogador.", value = false}, + {label = "Quando seu tio não vem te buscar na escola.", value = false}, + {label = "Eu não sei.", value = false} } }, { - question = 'Qual destes exemplos é da Regra de Morte Aleatória?', + question = "Qual destes exemplos é da Regra de Morte Aleatória?", options = { - {label = 'Você não pode atacar outro jogador aleatoriamente sem primeiro se envolver em algum tipo de RP verbal.', value = true}, - {label = 'Você pode matar outros jogadores sem motivo.', value = false}, - {label = 'Você não pode comprar água a menos que seja um apoiador do servidor.', value = false}, - {label = 'Eu não sei.', value = false} + { + label = "Você não pode atacar outro jogador aleatoriamente sem primeiro se envolver em algum tipo de RP verbal.", + value = true + }, + {label = "Você pode matar outros jogadores sem motivo.", value = false}, + {label = "Você não pode comprar água a menos que seja um apoiador do servidor.", value = false}, + {label = "Eu não sei.", value = false} } } }, + PreExamQuestions = { + Enabled = false, + FormatPhone = true, + WebHook = "", -- Discord Webhook URL + label = "Precisamos de algumas informações:", + information = { + { + type = "input", -- https://docs.mriqbox.com.br/overextended/ox_lib/Modules/Interface/Client/input#field-type-properties + label = "Qual seu nome completo (Vida Real):", + placeholder = "Seu nome", + required = true, + min = 3, + max = 100, + kind = "name" + }, + { + type = "input", -- https://docs.mriqbox.com.br/overextended/ox_lib/Modules/Interface/Client/input#field-type-properties + label = "Qual o seu e-mail?", + placeholder = "seu@email.com", + min = 7, + max = 50, + required = true, + kind = "email" + }, + { + type = "number", -- https://docs.mriqbox.com.br/overextended/ox_lib/Modules/Interface/Client/input#field-type-properties + label = "Qual o seu WhatsApp?", + placeholder = "9999999999", + required = true, + kind = "phone" + }, + } + } } diff --git a/server/main.lua b/server/main.lua index 1d8021c..cbac3aa 100644 --- a/server/main.lua +++ b/server/main.lua @@ -1,3 +1,7 @@ +local function RGBToLong(cor) + return (cor.r * 65536) + (cor.g * 256) + cor.b +end + local function GetPlayer(identifier, notifySource) if tonumber(identifier) then return exports.qbx_core:GetPlayer(identifier) @@ -54,7 +58,6 @@ local function SetPlayerBucket(target, bucket) end local function Initialize() - local success, result = pcall(MySQL.scalar.await, "SELECT 1 FROM mri_qwhitelist") if not success then @@ -85,11 +88,14 @@ local function Initialize() GetConfig() end -AddEventHandler('onResourceStart', function(resource) - if resource == GetCurrentResourceName() then - Initialize() - end -end) +AddEventHandler( + "onResourceStart", + function(resource) + if resource == GetCurrentResourceName() then + Initialize() + end + end +) lib.callback.register( "mri_Qwhitelist:Server:GetConfig", @@ -127,7 +133,6 @@ lib.callback.register( lib.callback.register( "mri_Qwhitelist:Server:AddCitizenship", function(source, identifier) - local player = GetPlayer(identifier or source, identifier and source or nil) if not player then return false @@ -136,7 +141,14 @@ lib.callback.register( local status = AddCitizenship(player.PlayerData.citizenid, identifier or source) if not status then if identifier then - lib.notify(source, {description = "Erro ao liberar player, verifique o console para mais informações.", type = "error", duration = 5000}) + lib.notify( + source, + { + description = "Erro ao liberar player, verifique o console para mais informações.", + type = "error", + duration = 5000 + } + ) end return status end @@ -150,7 +162,6 @@ lib.callback.register( lib.callback.register( "mri_Qwhitelist:Server:RemoveCitizenship", function(source, identifier) - local player = GetPlayer(identifier) if not player then return false @@ -158,7 +169,14 @@ lib.callback.register( local status = RemoveCitizenship(player.PlayerData.citizenid, identifier) if not status then - lib.notify(source, {description = "Erro ao revogar whitelist, verifique o console para mais informações.", type = "error", duration = 5000}) + lib.notify( + source, + { + description = "Erro ao revogar whitelist, verifique o console para mais informações.", + type = "error", + duration = 5000 + } + ) end SetPlayerBucket(player.PlayerData.source, 1000 + player.PlayerData.source) @@ -166,3 +184,93 @@ lib.callback.register( return status end ) + +lib.callback.register( + "mri_Qwhitelist:Server:SendPreExamData", + function(source, data) + if not Config.PreExamQuestions.WebHook then + print("Sem webhook para enviar os dados...") + return + end + local color = + RGBToLong( + { + r = 0, + g = 255, + b = 255 + } + ) + local player = GetPlayer(source) + if not player then + return + end + local fields = { + { + name = "Identificador:", + value = player.PlayerData.name, + inline = true + }, + { + name = "CitizenID:", + value = player.PlayerData.citizenid, + inline = true + }, + { + name = "Nome do Player:", + value = string.format( + "%s %s", + player.PlayerData.charinfo.firstname, + player.PlayerData.charinfo.lastname + ), + inline = false + } + } + for k, v in pairs(data) do + local value = v.value + if v.kind == "phone" and Config.PreExamQuestions.FormatPhone then + value = string.format("https://wa.me/55%s", value) + end + fields[#fields + 1] = { + name = k, + value = value, + inline = false + } + end + local obj = + json.encode( + { + embeds = { + { + title = "Dados Pré-Exame", + fields = fields, + footer = { + text = "MRI QBOX ⋅ " .. os.date("%d/%m/%Y %X"), + icon_url = "https://assets.mriqbox.com.br/branding/logo96.png" + }, + color = color + } + } + } + ) + PerformHttpRequest( + Config.PreExamQuestions.WebHook, + function(errorCode, resultData, resultHeaders, errorData) + if Config.DebugHook then + print( + string.format( + "Webhook:\n\tCódigo: %s\n\tResultado: %s\n\tErro: %s", + errorCode, + ttc.shared.toString(resultData), + ttc.shared.toString(errorData) + ) + ) + end + end, + "POST", + obj, + { + ["Content-Type"] = "application/json" + } + ) + end +)