This commit is contained in:
lifestorm
2024-08-04 22:55:00 +03:00
parent 0e770b2b49
commit 94063e4369
7342 changed files with 1718932 additions and 14 deletions

View File

@@ -0,0 +1,39 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PLUGIN = PLUGIN
function PLUGIN:AddQuiz(question, answers, bPermanent)
netstream.Start("AddQuiz", question, answers, bPermanent)
end
function PLUGIN:RemoveQuiz(id)
netstream.Start("RemoveQuiz", id)
end
function PLUGIN:EditQuiz(id, question, answers, bPermanent)
netstream.Start("EditQuiz", id, question, answers, bPermanent)
end
-- Hooks
netstream.Hook("SyncQuiz", function(list)
PLUGIN.quizlist = list
if IsValid(ix.gui.quizAnswering) then
if (ix.gui.quizAnswering.CreateQuizContent) then
ix.gui.quizAnswering:CreateQuizContent()
end
end
if IsValid(ix.gui.quizMenu) then
if (ix.gui.quizMenu.CreateLeftSide) then
ix.gui.quizMenu:CreateLeftSide()
end
end
end)

View File

@@ -0,0 +1,291 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PLUGIN = PLUGIN
local PANEL = {}
local margin10 = SScaleMin(10 / 3)
local size50 = SScaleMin(50 / 3)
function PANEL:Init()
ix.gui.quizMenu = self
self:SetSize(SScaleMin(600 / 3), SScaleMin(500 / 3))
self:Center()
self:SetTitle("Quiz Manager")
DFrameFixer(self)
self.leftSide = self:Add("Panel")
self.leftSide:Dock(LEFT)
self.leftSide:SetWide(self:GetWide() * 0.5)
self.leftSide:DockMargin(0, 0, margin10, 0)
local divider = self:Add("DShape")
divider:Dock(LEFT)
divider:SetWide(SScaleMin(1 / 3))
divider:SetType("Rect")
divider:DockMargin(0, 0, margin10, 0)
divider:SetColor(Color(111, 111, 136, (255 / 100 * 30)))
self.rightSide = self:Add("Panel")
self.rightSide:Dock(FILL)
self:CreateRightSide()
netstream.Start("RequestQuizzes", true)
end
function PANEL:CreateRightTitle()
self:CreateTitle(self.rightSide, "Question Editor")
end
function PANEL:CreateLeftTitle()
self:CreateTitle(self.leftSide, "Current Questions")
end
function PANEL:CreateTitle(parent, text, font)
local title = parent:Add("DLabel")
title:Dock(TOP)
title:SetText(text)
title:SetFont(font or "LargerTitlesFontNoClamp")
title:SetContentAlignment(5)
title:SizeToContents()
title:DockMargin(0, 0, 0, margin10)
end
function PANEL:CreateLeftSide()
for _, v in pairs(self.leftSide:GetChildren()) do
v:Remove()
end
self:CreateLeftTitle()
local addQuiz = self.leftSide:Add("DButton")
addQuiz:Dock(BOTTOM)
addQuiz:SetTall(size50)
addQuiz:SetText("ADD QUESTION")
addQuiz:SetFont("MenuFontLargerNoClamp")
addQuiz:DockMargin(0, margin10, 0, 0)
addQuiz.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
if self.quizAddEditPanel then
self.quizAddEditPanel:Remove()
self.quizAddEditPanel = nil
end
self:CreateQuizAddPanel()
end
self.quizScroll = self.leftSide:Add("DScrollPanel")
self.quizScroll:Dock(FILL)
self:RefreshQuizzes()
end
function PANEL:CreateRightSide()
self:CreateRightTitle()
end
function PANEL:RefreshQuizzes()
for id, table in pairs(PLUGIN.quizlist) do
local question = table[1] or "NO QUESTION"
local answers = table[2] or {}
local quiz = self.quizScroll:Add("DButton")
quiz:Dock(TOP)
quiz:SetTall(size50)
quiz:SetText(question and (string.len(question) > 30 and string.Left(question, 30).."..." or question) or "")
quiz:SetContentAlignment(4)
quiz:SetTextInset(margin10, 0)
quiz:SetFont("MenuFontLargerNoClamp")
quiz.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
if self.quizAddEditPanel then
self.quizAddEditPanel:Remove()
self.quizAddEditPanel = nil
end
self:CreateQuizAddPanel(id, table)
end
local deleteQuiz = quiz:Add("DButton")
deleteQuiz:Dock(RIGHT)
deleteQuiz:DockMargin(margin10, margin10 * 1.5, 0, margin10 * 1.5)
deleteQuiz:SetWide(SScaleMin(30 / 3))
deleteQuiz:SetText("")
deleteQuiz.Paint = function(self, w, h)
surface.SetDrawColor(color_white)
surface.SetMaterial(ix.util.GetMaterial("materials/willardnetworks/tabmenu/navicons/exit.png"))
surface.DrawTexturedRect(0, 0, w - SScaleMin(10 / 3), h)
end
deleteQuiz.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
PLUGIN:RemoveQuiz(id)
quiz:Remove()
end
end
end
function PANEL:CreateQuizAddPanel(id, table)
self.answers = {}
self.question = ""
self.quizAddEditPanel = self.rightSide:Add("EditablePanel")
self.quizAddEditPanel:Dock(FILL)
self:CreateTitle(self.quizAddEditPanel, "Question", "MenuFontNoClamp")
local question = self.quizAddEditPanel:Add("DTextEntry")
question:Dock(TOP)
question:SetTall(SScaleMin(30 / 3))
question:DockMargin(0, 0, 0, margin10)
question:SetZPos(1)
self:CreateTextEntry(question, id and table[1] or "A cool question")
local addAnswer = self.quizAddEditPanel:Add("DButton")
addAnswer:Dock(TOP)
addAnswer:DockMargin(0, 0, 0, margin10)
addAnswer:SetFont("MenuFontLargerNoClamp")
addAnswer:SetText("ADD ANSWER(S)")
addAnswer:SetTall(size50)
addAnswer:SetZPos(2)
addAnswer.DoClick = function()
if #self.answers == 6 then return LocalPlayer():NotifyLocalized("Max answers is 6!") end
self:CreateAnswer(self.quizAddEditPanel)
end
if !id then
for i = 1, 2 do
addAnswer.DoClick()
end
local firstAnswer = self.answers[1]:GetChildren()[1]
firstAnswer.DoClick(firstAnswer)
self.answers[1]:SetText("A right answer")
self.answers[2]:SetText("A wrong answer")
else
for answer, rightAnswer in pairs(table[2]) do
self:CreateAnswer(self.quizAddEditPanel, answer, rightAnswer)
end
end
local bPermanent = self.quizAddEditPanel:Add("DCheckBoxLabel")
bPermanent:Dock(BOTTOM)
bPermanent:SetZPos(4)
bPermanent:SetFont("MenuFontNoClamp")
bPermanent:SetText("Permanent Question")
bPermanent:SizeToContents()
bPermanent:DockMargin(0, 0, 0, SScaleMin(10 / 3))
bPermanent:SetValue(id and table[3] or false)
local saveQuiz = self.quizAddEditPanel:Add("DButton")
saveQuiz:Dock(BOTTOM)
saveQuiz:SetTall(size50)
saveQuiz:SetZPos(3)
saveQuiz:SetText(id and "EDIT" or "SAVE")
saveQuiz:SetFont("MenuFontLargerNoClamp")
saveQuiz.DoClick = function()
surface.PlaySound("helix/ui/press.wav")
self.question = question:GetText()
self:SaveQuiz(id, bPermanent:GetChecked())
self.quizAddEditPanel:Remove()
end
end
function PANEL:CreateAnswer(parent, sAnswer, bRightAnswer)
local answerPanel = parent:Add("Panel")
answerPanel:Dock(TOP)
answerPanel:SetTall(SScaleMin(30 / 3))
answerPanel:SetZPos(5)
local answer = answerPanel:Add("DTextEntry")
answer:Dock(LEFT)
answer:SetWide(SScaleMin(267 / 3))
answer:SetText(sAnswer or "")
self:CreateTextEntry(answer, sAnswer or "", 30, true)
answer.rightAnswer = bRightAnswer or false
local trueOrFalse = answer:Add("DButton")
trueOrFalse:Dock(RIGHT)
trueOrFalse:SetWide(SScaleMin(30 / 3))
trueOrFalse:SetText("")
trueOrFalse.Paint = function(self, w, h)
if self:GetParent().rightAnswer then
surface.SetDrawColor(color_white)
surface.SetMaterial(ix.util.GetMaterial("materials/willardnetworks/charselect/check.png"))
surface.DrawTexturedRect(SScaleMin(5 / 3), SScaleMin(5 / 3), w - margin10, h - margin10)
else
surface.SetDrawColor(color_white)
surface.SetMaterial(ix.util.GetMaterial("materials/willardnetworks/tabmenu/navicons/exit.png"))
surface.DrawTexturedRect(SScaleMin(5 / 3), SScaleMin(5 / 3), w - margin10, h - margin10)
end
end
trueOrFalse.DoClick = function(this)
if !this:GetParent().rightAnswer then
this:GetParent().rightAnswer = true
end
for _, v in pairs(self.answers) do
v.rightAnswer = false
end
this:GetParent().rightAnswer = true
end
table.insert(self.answers, answer)
end
function PANEL:SaveQuiz(id, bPermanent)
local answers = {}
for _, v in pairs(self.answers) do
answers[v:GetText()] = v.rightAnswer
end
if id then
PLUGIN:EditQuiz(id, self.question, answers, bPermanent)
else
PLUGIN:AddQuiz(self.question, answers, bPermanent)
end
end
function PANEL:CreateTextEntry(parent, value, maxChars, bShouldBePaintedShorter)
parent:SetTextColor(Color(200, 200, 200, 255))
parent:SetCursorColor(Color(200, 200, 200, 255))
parent:SetFont("MenuFontNoClamp")
parent:SetText(value or "")
parent.Paint = function(self, w, h)
surface.SetDrawColor(Color(0, 0, 0, 100))
surface.DrawRect(0, 0, bShouldBePaintedShorter and (w - SScaleMin(30 / 3) - margin10) or w, h)
surface.SetDrawColor(Color(111, 111, 136, (255 / 100 * 30)))
surface.DrawOutlinedRect(0, 0, bShouldBePaintedShorter and (w - SScaleMin(30 / 3) - margin10) or w, h)
self:DrawTextEntryText( self:GetTextColor(), self:GetHighlightColor(), self:GetCursorColor() )
end
if maxChars then
parent.MaxChars = maxChars
parent.AllowInput = function()
local value2 = parent:GetValue()
if (string.utf8len(value2) > maxChars) then
return true
end
end
end
end
vgui.Register("QuizPanel", PANEL, "DFrame")

View File

@@ -0,0 +1,242 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PLUGIN = PLUGIN
PLUGIN.quizlist = PLUGIN.quizlist or {}
function PLUGIN:DatabaseConnected()
local query = mysql:Create("ix_storedquiz")
query:Create("quiz_id", "INT(11) UNSIGNED NOT NULL AUTO_INCREMENT")
query:Create("quiz_question", "TEXT")
query:Create("quiz_answers", "TEXT")
query:Create("quiz_permanent", "TEXT")
query:PrimaryKey("quiz_id")
query:Callback(function()
local quizQuery = mysql:Select("ix_storedquiz")
quizQuery:Callback(function(quizResult)
if (!istable(quizResult) or #quizResult == 0) then
return
end
for _, v in ipairs(quizResult) do
self.quizlist[tonumber(v["quiz_id"])] = {v["quiz_question"], util.JSONToTable(v["quiz_answers"]), v["quiz_permanent"]}
end
end)
quizQuery:Execute()
end)
query:Execute()
end
function PLUGIN:RandomQuizzes(client, newQuizList)
-- Thanks Gr4Ss
client.sentQuizIDs = {}
local keys = {}
local quiz = {}
for k, v in pairs(newQuizList) do
if (v[3] == true) then
quiz[#quiz + 1] = v
client.sentQuizIDs[#quiz] = k
else
keys[#keys + 1] = k
end
end
while (#quiz < 6 and #keys > 0) do
local winner = math.random(#keys)
quiz[#quiz + 1] = newQuizList[keys[winner]]
client.sentQuizIDs[#quiz] = keys[winner]
table.remove(keys, winner)
end
netstream.Start(client, "SyncQuiz", quiz)
end
function PLUGIN:ReplyQuizzes(client, bAdmin)
if (bAdmin) then
if (client:IsAdmin()) then
self:SyncFullQuizList(client)
else
ix.log.Add(client, "luaHack", "accéder à la quizlist complète sans administrateur")
client:Kick("Vous n'êtes pas un administrateur.")
end
return false
end
local newQuizList = {}
for oldKey, tQuestion in pairs(self.quizlist) do
newQuizList[oldKey] = {tQuestion[1], {}, tQuestion[3]}
for answer, _ in pairs(tQuestion[2]) do
newQuizList[oldKey][2][#newQuizList[oldKey][2] + 1] = answer
end
end
self:RandomQuizzes(client, newQuizList)
end
function PLUGIN:SyncFullQuizList(client)
netstream.Start(client, "SyncQuiz", self.quizlist)
end
netstream.Hook("RequestQuizzes", function(client, bAdmin)
PLUGIN:ReplyQuizzes(client, bAdmin)
end)
function PLUGIN:AddQuiz(client, question, answers, bPermanent)
if (!client:IsAdmin()) then
ix.log.Add(client, "luaHack", "accéder à QuizAdd")
client:Kick("Vous n'êtes pas un administrateur.")
return false
end
PLUGIN.quizlist[#PLUGIN.quizlist + 1] = {question, answers, bPermanent}
local queryAdd = mysql:Insert("ix_storedquiz")
queryAdd:Insert("quiz_question", question)
queryAdd:Insert("quiz_answers", util.TableToJSON(answers))
queryAdd:Insert("quiz_permanent", bPermanent)
queryAdd:Execute()
self:SyncFullQuizList(client)
end
function PLUGIN:RemoveQuiz(client, id)
if (!client:IsAdmin()) then
ix.log.Add(client, "luaHack", "access QuizRemove")
client:Kick("Vous n'êtes pas un administrateur.")
return false
end
PLUGIN.quizlist[id] = nil
local queryDelete = mysql:Delete("ix_storedquiz")
queryDelete:Where("quiz_id", id)
queryDelete:Execute()
self:SyncFullQuizList(client)
end
function PLUGIN:EditQuiz(client, id, question, answers, bPermanent)
if !client:IsAdmin() then
ix.log.Add(client, "luaHack", "access QuizEdit")
client:Kick("Vous n'êtes pas un administrateur.")
return false
end
PLUGIN.quizlist[id] = {question, answers, bPermanent}
local queryEdit = mysql:Update("ix_storedquiz")
queryEdit:Where("quiz_id", id)
queryEdit:Update("quiz_question", question)
queryEdit:Update("quiz_answers", util.TableToJSON(answers))
queryEdit:Update("quiz_permanent", bPermanent)
queryEdit:Execute()
self:SyncFullQuizList(client)
end
function PLUGIN:CheckIfAnswersAreRight(client, answers)
if !client.sentQuizIDs then return false end
for sendID, actualAnswer in pairs(answers) do
local realID = client.sentQuizIDs[sendID]
if (!realID) then
ix.log.Add(client, "luaHack", "modifier les questions posées au quiz")
return false
end
local question = self.quizlist[realID]
local bAnswerFound = false
if question then
for answer, bRightAnswer in pairs(question[2]) do
if (answer == actualAnswer) then
if (bRightAnswer != true) then
return false
else
bAnswerFound = true
break
end
end
end
end
if (!bAnswerFound) then return false end
end
return true
end
function PLUGIN:AnswersMissing(client, answers)
if (!client.sentQuizIDs) then
return true
end
if (table.Count(answers) != #client.sentQuizIDs) then
return true
end
return false
end
function PLUGIN:CanPlayerCreateCharacter(client)
if (!client:GetData("QuizCompleted", false)) then
ix.log.Add(client, "luaHack", "contourner la vérification du quiz de création de personnage")
return false, "Bien essayé !"
end
end
function PLUGIN:CompleteQuiz(client, answers)
if (self:AnswersMissing(client, answers)) then
netstream.Start(client, "SendCharacterPanelNotify", "Il vous manque encore des réponses à certaines questions !")
return false
end
if (!self:CheckIfAnswersAreRight(client, answers)) then
local quizAttempts = client:GetNetVar("quizAttempts", 3)
if (quizAttempts > 1) then
local remainingAttempts = quizAttempts - 1
local notification = string.format("Une ou plusieurs de vos réponses étaient incorrectes. Veuillez lire les règles et les directives et réessayer. Il vous reste %d tentative%s.", remainingAttempts, remainingAttempts > 1 and "s" or "")
netstream.Start(client, "SendCharacterPanelNotify", notification)
client:SetNetVar("quizAttempts", remainingAttempts)
else
client:Kick("Malheureusement, vous n'avez pas répondu correctement. Veuillez lire les règles et directives sur https://discord.gg/dWJqGfyYJ8 et réessayer")
end
return false
end
client:SetData("QuizCompleted", true)
client.sentQuizIDs = nil
netstream.Start(client, "SendCharacterPanelNotify", "Félicitation, vous avez répondu correctement et vous pouvez maintenant créer un personnage !")
netstream.Start(client, "RemoveQuizUI")
end
-- Hooks
netstream.Hook("AddQuiz", function(client, question, answers, bPermanent)
PLUGIN:AddQuiz(client, question, answers, bPermanent)
end)
netstream.Hook("RemoveQuiz", function(client, id)
PLUGIN:RemoveQuiz(client, id)
end)
netstream.Hook("EditQuiz", function(client, id, question, answers, bPermanent)
PLUGIN:EditQuiz(client, id, question, answers, bPermanent)
end)
netstream.Hook("CompleteQuiz", function(client, answers)
PLUGIN:CompleteQuiz(client, answers)
end)