Initial commit

This commit is contained in:
pavetr
2026-03-15 14:54:49 +03:00
commit 64f8029c06
4027 changed files with 254888 additions and 0 deletions

View File

@@ -0,0 +1,216 @@
local QuestionVGUI = {}
local PanelNum = 0
local VoteVGUI = {}
local function MsgDoVote(msg)
local _, chatY = chat.GetChatBoxPos()
local question = msg:ReadString()
local voteid = msg:ReadShort()
local timeleft = msg:ReadFloat()
if timeleft == 0 then
timeleft = 100
end
local OldTime = CurTime()
if not IsValid(LocalPlayer()) then return end -- Sent right before player initialisation
LocalPlayer():EmitSound("Town.d1_town_02_elevbell1", 100, 100)
local panel = vgui.Create("DFrame")
panel:SetPos(3 + PanelNum, chatY - 145)
panel:SetTitle(DarkRP.getPhrase("vote"))
panel:SetSize(140, 140)
panel:SetSizable(false)
panel.btnClose:SetVisible(false)
panel.btnMaxim:SetVisible(false)
panel.btnMinim:SetVisible(false)
panel:SetDraggable(false)
function panel:Close()
PanelNum = PanelNum - 140
VoteVGUI[voteid .. "vote"] = nil
local num = 0
for _, v in SortedPairs(VoteVGUI) do
v:SetPos(num, ScrH() / 2 - 50)
num = num + 140
end
for _, v in SortedPairs(QuestionVGUI) do
v:SetPos(num, ScrH() / 2 - 50)
num = num + 300
end
self:Remove()
end
function panel:Think()
self:SetTitle(DarkRP.getPhrase("time", math.Clamp(math.ceil(timeleft - (CurTime() - OldTime)), 0, 9999)))
if timeleft - (CurTime() - OldTime) <= 0 then
panel:Close()
end
end
panel:SetKeyboardInputEnabled(false)
panel:SetMouseInputEnabled(true)
panel:SetVisible(true)
local label = vgui.Create("DLabel")
label:SetParent(panel)
label:SetPos(5, 25)
label:SetText(DarkRP.textWrap(DarkRP.deLocalise(question), "DermaDefault", 130))
label:SizeToContents()
label:SetVisible(true)
local nextHeight = label:GetTall() > 78 and label:GetTall() - 78 or 0 -- Make panel taller for buttons
panel:SetTall(panel:GetTall() + nextHeight)
local ybutton = vgui.Create("Button")
ybutton:SetParent(panel)
ybutton:SetPos(25, panel:GetTall() - 25)
ybutton:SetSize(40, 20)
ybutton:SetText(DarkRP.getPhrase("yes"))
ybutton:SetVisible(true)
ybutton.DoClick = function()
LocalPlayer():ConCommand("vote " .. voteid .. " yea\n")
panel:Close()
end
local nbutton = vgui.Create("Button")
nbutton:SetParent(panel)
nbutton:SetPos(70, panel:GetTall() - 25)
nbutton:SetSize(40, 20)
nbutton:SetText(DarkRP.getPhrase("no"))
nbutton:SetVisible(true)
nbutton.DoClick = function()
LocalPlayer():ConCommand("vote " .. voteid .. " nay\n")
panel:Close()
end
PanelNum = PanelNum + 140
VoteVGUI[voteid .. "vote"] = panel
panel:SetSkin(GAMEMODE.Config.DarkRPSkin)
end
usermessage.Hook("DoVote", MsgDoVote)
local function KillVoteVGUI(msg)
local id = msg:ReadShort()
if VoteVGUI[id .. "vote"] and VoteVGUI[id .. "vote"]:IsValid() then
VoteVGUI[id .. "vote"]:Close()
end
end
usermessage.Hook("KillVoteVGUI", KillVoteVGUI)
local function MsgDoQuestion(msg)
if not IsValid(LocalPlayer()) then return end
local question = msg:ReadString()
local quesid = msg:ReadString()
local timeleft = msg:ReadFloat()
if timeleft == 0 then
timeleft = 100
end
local OldTime = CurTime()
LocalPlayer():EmitSound("Town.d1_town_02_elevbell1", 100, 100)
local panel = vgui.Create("DFrame")
panel:SetPos(3 + PanelNum, ScrH() / 2 - 50) -- Times 140 because if the question is the second screen, the first screen is always a vote screen.
panel:SetSize(300, 140)
panel:SetSizable(false)
panel.btnClose:SetVisible(false)
panel.btnMaxim:SetVisible(false)
panel.btnMinim:SetVisible(false)
panel:SetKeyboardInputEnabled(false)
panel:SetMouseInputEnabled(true)
panel:SetVisible(true)
function panel:Close()
PanelNum = PanelNum - 300
QuestionVGUI[quesid .. "ques"] = nil
local num = 0
for _, v in SortedPairs(VoteVGUI) do
v:SetPos(num, ScrH() / 2 - 50)
num = num + 140
end
for _, v in SortedPairs(QuestionVGUI) do
v:SetPos(num, ScrH() / 2 - 50)
num = num + 300
end
self:Remove()
end
function panel:Think()
self:SetTitle(DarkRP.getPhrase("time", math.Clamp(math.ceil(timeleft - (CurTime() - OldTime)), 0, 9999)))
if timeleft - (CurTime() - OldTime) <= 0 then
panel:Close()
end
end
local label = vgui.Create("DLabel")
label:SetParent(panel)
label:SetPos(5, 30)
label:SetSize(380, 40)
label:SetText(DarkRP.deLocalise(question))
label:SetVisible(true)
local ybutton = vgui.Create("DButton")
ybutton:SetParent(panel)
ybutton:SetPos(105, 100)
ybutton:SetSize(40, 20)
ybutton:SetText(DarkRP.getPhrase("yes"))
ybutton:SetVisible(true)
ybutton.DoClick = function()
LocalPlayer():ConCommand("ans " .. quesid .. " 1\n")
panel:Close()
end
local nbutton = vgui.Create("DButton")
nbutton:SetParent(panel)
nbutton:SetPos(155, 100)
nbutton:SetSize(40, 20)
nbutton:SetText(DarkRP.getPhrase("no"))
nbutton:SetVisible(true)
nbutton.DoClick = function()
LocalPlayer():ConCommand("ans " .. quesid .. " 2\n")
panel:Close()
end
PanelNum = PanelNum + 300
QuestionVGUI[quesid .. "ques"] = panel
panel:SetSkin(GAMEMODE.Config.DarkRPSkin)
end
usermessage.Hook("DoQuestion", MsgDoQuestion)
local function KillQuestionVGUI(msg)
local id = msg:ReadString()
if QuestionVGUI[id .. "ques"] and QuestionVGUI[id .. "ques"]:IsValid() then
QuestionVGUI[id .. "ques"]:Close()
end
end
usermessage.Hook("KillQuestionVGUI", KillQuestionVGUI)
local function DoVoteAnswerQuestion(ply, cmd, args)
if not args[1] then return end
local vote = 0
if tonumber(args[1]) == 1 or string.lower(args[1]) == "yes" or string.lower(args[1]) == "true" then vote = 1 end
for k, v in pairs(VoteVGUI) do
if IsValid(v) then
local ID = string.sub(k, 1, -5)
VoteVGUI[k]:Close()
RunConsoleCommand("vote", ID, vote)
return
end
end
for k, v in pairs(QuestionVGUI) do
if IsValid(v) then
local ID = string.sub(k, 1, -5)
QuestionVGUI[k]:Close()
RunConsoleCommand("ans", ID, vote)
return
end
end
end
concommand.Add("rp_vote", DoVoteAnswerQuestion)

View File

@@ -0,0 +1,5 @@
DarkRP.declareChatCommand{
command = "forcecancelvote",
description = "Forcefully cancel a vote.",
delay = 0.5
}

View File

@@ -0,0 +1,255 @@
DarkRP.createQuestion = DarkRP.stub{
name = "createQuestion",
description = "Ask someone a question.",
parameters = {
{
name = "question",
description = "The question to ask.",
type = "string",
optional = false
},
{
name = "quesid",
description = "A unique question id.",
type = "string",
optional = false
},
{
name = "target",
description = "Who to ask the question.",
type = "Player",
optional = false
},
{
name = "delay",
description = "For how long the player will be able to answer.",
type = "number",
optional = false
},
{
name = "callback",
description = "The function that gets called after the question.",
type = "function",
optional = false
},
{
name = "fromPly",
description = "The player who asked the question.",
type = "Player",
optional = true
},
{
name = "toPly",
description = "A third involved player.",
type = "Player",
optional = true
},
{
name = "...",
description = "Any other information.",
type = "any",
optional = true
}
},
returns = {
},
metatable = DarkRP
}
DarkRP.destroyQuestion = DarkRP.stub{
name = "destroyQuestion",
description = "Destroy a question by ID.",
parameters = {
{
name = "id",
description = "The id of the question.",
type = "string",
optional = false
}
},
returns = {
},
metatable = DarkRP
}
DarkRP.destroyQuestionsWithEnt = DarkRP.stub{
name = "destroyQuestionsWithEnt",
description = "Destroy all questions that have something to do with this ent.",
parameters = {
{
name = "ent",
description = "The Entity.",
type = "Entity",
optional = false
}
},
returns = {
},
metatable = DarkRP
}
DarkRP.createVote = DarkRP.stub{
name = "createVote",
description = "Create a vote.",
parameters = {
{
name = "question",
description = "The question to ask in the vote.",
type = "string",
optional = false
},
{
name = "voteid",
description = "A unique vote id.",
type = "string",
optional = false
},
{
name = "target",
description = "Whom the vote is about.",
type = "Player",
optional = false
},
{
name = "delay",
description = "For how long the player will be able to answer.",
type = "number",
optional = false
},
{
name = "callback",
description = "The function that gets called after the vote.",
type = "function",
optional = false
},
{
name = "excludeVoters",
description = "The players to exclude from voting.",
type = "table",
optional = true
},
{
name = "fail",
description = "A callback for when the vote fails.",
type = "function",
optional = true
},
{
name = "...",
description = "Any other information.\n\nIf the vote involves multiple parties (i.e. the target of the vote and person who started it are different) you should provide a table with the \"source\" field set to the player who intiated the vote. This ensures the notifications about the vote are sent to the correct player.",
type = "any",
optional = true
}
},
returns = {
{
name = "vote",
description = "All the vote information. Returns nil if the vote did not start because the canStartVote hook blocked it.",
type = "table"
}
},
metatable = DarkRP
}
DarkRP.destroyVotesWithEnt = DarkRP.stub{
name = "destroyVotesWithEnt",
description = "Destroy all votes that have something to do with this ent.",
parameters = {
{
name = "ent",
description = "The Entity.",
type = "Entity",
optional = false
}
},
returns = {
},
metatable = DarkRP
}
DarkRP.destroyLastVote = DarkRP.stub{
name = "destroyLastVote",
description = "Destroy the last created vote.",
parameters = {
},
returns = {
{
name = "destroyed",
description = "Whether there was a last vote to destroy or not.",
type = "boolean"
}
},
metatable = DarkRP
}
DarkRP.hookStub{
name = "getVoteResults",
description = "Override the results of a vote.",
parameters = {
{
name = "vote",
description = "A table that contains information about the vote.",
type = "table"
},
{
name = "yea",
description = "The amount of people that voted yes.",
type = "number"
},
{
name = "nay",
description = "The amount of people that voted no.",
type = "number"
}
},
returns = {
{
name = "result",
description = "The result of the vote. Return 1 for win, -1 for lose, 0 for undecided.",
type = "number"
}
}
}
DarkRP.hookStub{
name = "canStartVote",
description = "Whether the vote can be started or not.",
parameters = {
{
name = "vote",
description = "A table that contains information about the vote.",
type = "table"
}
},
returns = {
{
name = "canStartVote",
description = "Whether the vote can be started or not.",
type = "boolean"
},
{
name = "callSuccess",
description = "True if the callback for a successful vote should be called, false if the callback for a failed vote should be called. Only works when canStartVote is false.",
type = "boolean"
},
{
name = "message",
description = "The message to show when the vote cannot be started. Only works when callSuccess is false.",
type = "string"
}
}
}
DarkRP.hookStub{
name = "onVoteStarted",
description = "Called when a vote has been started.",
parameters = {
{
name = "vote",
description = "A table that contains information about the vote.",
type = "table"
}
},
returns = {
}
}

View File

@@ -0,0 +1,67 @@
local Question = {}
local Questions = {}
local function ccDoQuestion(ply, cmd, args)
local q = Questions[args[1]]
if not q then return end
if not tonumber(args[2]) then return end
if q.Ent and q.Ent ~= ply then return end
q:handleNewQuestion(tonumber(args[2]))
end
concommand.Add("ans", ccDoQuestion)
local function handleQuestionEnd(id)
if not Questions[id] then return end
local q = Questions[id]
q.Callback(q.yn, q.Ent, q.Initiator, q.Target, unpack(q.Args))
Questions[id] = nil
end
function Question:handleNewQuestion(response)
if response == 1 or response == 0 then
self.yn = tobool(response)
end
handleQuestionEnd(self.ID)
end
function DarkRP.createQuestion(question, quesid, ent, delay, callback, fromPly, toPly, ...)
local newques = {}
for k, v in pairs(Question) do newques[k] = v end
newques.ID = quesid
newques.Callback = callback
newques.Ent = ent
newques.Initiator = fromPly
newques.Target = toPly
newques.Args = {...}
newques.yn = 0
Questions[quesid] = newques
umsg.Start("DoQuestion", ent)
umsg.String(question)
umsg.String(quesid)
umsg.Float(delay)
umsg.End()
timer.Create(quesid .. "timer", delay, 1, function() handleQuestionEnd(quesid) end)
end
function DarkRP.destroyQuestion(id)
umsg.Start("KillQuestionVGUI", Questions[id].Ent)
umsg.String(Questions[id].ID)
umsg.End()
Questions[id] = nil
end
function DarkRP.destroyQuestionsWithEnt(ent)
for _, v in pairs(Questions) do
if v.Ent == ent then
DarkRP.destroyQuestion(v.ID)
end
end
end

View File

@@ -0,0 +1,177 @@
local Vote = {}
local Votes = {}
local function ccDoVote(ply, cmd, args)
if ply:EntIndex() == 0 then
print(DarkRP.getPhrase("cmd_cant_be_run_server_console"))
return
end
local vote = Votes[tonumber(args[1] or 0)]
if not vote then return end
if args[2] ~= "yea" and args[2] ~= "nay" then return end
local canVote, message = hook.Call("canVote", GAMEMODE, ply, vote)
if vote.voters[ply] or vote.exclude[ply] or canVote == false then
DarkRP.notify(ply, 1, 4, message or DarkRP.getPhrase("you_cannot_vote"))
return
end
vote.voters[ply] = true
vote:handleNewVote(ply, args[2])
end
concommand.Add("vote", ccDoVote)
function Vote:handleNewVote(ply, choice)
self[choice] = self[choice] + 1
local excludeCount = table.Count(self.exclude)
local voteCount = table.Count(self.voters)
if voteCount >= player.GetCount() - excludeCount then
self:handleEnd()
end
end
function Vote:handleEnd()
local win = hook.Call("getVoteResults", nil, self, self.yea, self.nay)
win = win or self.yea > self.nay and 1 or self.nay > self.yea and -1 or 0
umsg.Start("KillVoteVGUI", self:getFilter())
umsg.String(self.id)
umsg.End()
Votes[self.id] = nil
timer.Remove(self.id .. "DarkRPVote")
self:callback(win)
end
function Vote:getFilter()
local filter = RecipientFilter()
for _, v in ipairs(player.GetAll()) do
if self.exclude[v] then continue end
local canVote = hook.Call("canVote", GAMEMODE, v, self)
if canVote == false then
self.exclude[v] = true
continue
end
filter:AddPlayer(v)
end
return filter
end
function DarkRP.hooks:canStartVote(newvote)
if player.GetCount() <= table.Count(newvote.exclude) then
local ply = istable(newvote.info) and isentity(newvote.info.source) and newvote.info.source or newvote.target
if ply and ply:IsPlayer() then
DarkRP.notify(ply, 0, 4, DarkRP.getPhrase("vote_alone"))
end
return false, true
end
return true
end
function DarkRP.createVote(question, voteType, target, time, callback, excludeVoters, fail, extraInfo)
excludeVoters = excludeVoters or {[target] = true}
local newvote = {}
setmetatable(newvote, {__index = Vote})
newvote.id = table.insert(Votes, newvote)
newvote.question = question
newvote.votetype = voteType
newvote.target = target
newvote.time = time
newvote.callback = callback
newvote.fail = fail or function() end
newvote.exclude = excludeVoters
newvote.voters = {}
newvote.info = extraInfo
newvote.yea = 0
newvote.nay = 0
local ply = istable(extraInfo) and isentity(extraInfo.source) and extraInfo.source or target
local canStart, callSuccess, message = hook.Call("canStartVote", DarkRP.hooks, newvote)
if not canStart then
if callSuccess then
newvote:callback(1)
else
if ply:IsPlayer() then
DarkRP.notify(ply, 1, 4, message or DarkRP.getPhrase("unable", DarkRP.getPhrase("create_vote_for_job"), ""))
end
newvote:fail()
end
return
end
hook.Call("onVoteStarted", nil, newvote)
if ply:IsPlayer() then
DarkRP.notify(ply, 0, 4, DarkRP.getPhrase("vote_started"))
end
umsg.Start("DoVote", newvote:getFilter())
umsg.String(question)
umsg.Short(newvote.id)
umsg.Float(time)
umsg.End()
timer.Create(newvote.id .. "DarkRPVote", time, 1, function() newvote:handleEnd() end)
return newvote
end
function DarkRP.destroyVotesWithEnt(ent)
for k, v in pairs(Votes) do
if v.target ~= ent then continue end
timer.Remove(v.id .. "DarkRPVote")
umsg.Start("KillVoteVGUI", v:getFilter())
umsg.Short(v.id)
umsg.End()
v:fail()
Votes[k] = nil
end
end
function DarkRP.destroyLastVote()
local lastVote = Votes[#Votes]
if not lastVote then return false end
timer.Remove(lastVote.id .. "DarkRPVote")
umsg.Start("KillVoteVGUI", lastVote:getFilter())
umsg.Short(lastVote.id)
umsg.End()
lastVote:fail()
Votes[lastVote.id] = nil
return true
end
local function CancelVote(ply)
local result = DarkRP.destroyLastVote()
if result then
DarkRP.notifyAll(0, 4, DarkRP.getPhrase("x_cancelled_vote", ply:EntIndex() ~= 0 and ply:Nick() or "Console"))
if ply:EntIndex() == 0 then
print(DarkRP.getPhrase("x_cancelled_vote", "Console"))
end
else
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("cant_cancel_vote"))
end
end
DarkRP.definePrivilegedChatCommand("forcecancelvote", "DarkRP_AdminCommands", CancelVote)