Physgun Wiki

Как сделать голосование

Голосования — общий механизм: сервер рассылает вопрос всем, кроме исключённых, собирает ответы и вызывает колбэк. На нём построены устройство на работу и увольнение.

Запуск

roleplay.Vote.Start(id, text, delay, onPass, exclude, onFail)
Аргумент Смысл
id уникальный идентификатор голосования
text вопрос, который увидят игроки
delay сколько секунд идёт голосование
onPass function(yes, no) — вызывается, если «за» больше, чем «против»
exclude массив игроков, которых не спрашивают
onFail function(yes, no) — необязательный, вызывается при отказе

Функция возвращает false, если голосование с таким id уже идёт или спрашивать оказалось некого.

local id = 'job_vote_' .. sender:UserID() local started = roleplay.Vote.Start(id, roleplay.L('JobVoteRequest', sender:Nick(), job.DisplayName), 20, function(yes, no) if (!IsValid(sender)) then return end sender:SetJob(job) end, { sender }, function() if (!IsValid(sender)) then return end sender:ChatError('JobVoteRejected', job.DisplayName) end)

Идентификатор

id должен быть уникальным для сущности голосования, а не для попытки. Идиома проекта — привязка к UserID игрока:

'job_vote_' .. sender:UserID() 'demote_vote_' .. target:UserID()

Так второе голосование за того же игрока не запустится, пока не закончилось первое, а отменить его можно, зная только игрока.

Если голосовать некому

Когда на сервере нет никого, кроме инициатора, Start возвращает false и колбэки не вызываются. Это не ошибка — обработайте случай явно, иначе действие просто не произойдёт:

if (!started) then sender:SetJob(job) end

Именно так работает устройство на работу в одиночку.

Досрочное завершение

Голосование заканчивается само по таймеру, но закрывается раньше, если проголосовали все.

roleplay.Vote.Cancel(id)

Отмена снимает голосование без вызова колбэков и убирает окно у тех, кто ещё не ответил.

Уборка за игроком

Когда игрок выходит, его надо снять со всех голосований, иначе они будут ждать ответа, которого не будет. Своего hook.Add при этом заводить не нужно: модуль отдаёт функцию, а вызов дописывается в единственный GM:PlayerDisconnected в sv_player.lua.

function GM:PlayerDisconnected(ply) ... roleplay.CancelJobVotes(ply) roleplay.Vote.Cleanup(ply) end

Cleanup убирает игрока из списков голосующих и завершает голосование, если он был последним, кто не ответил.

Со стороны игрока

Окно рисуется на клиенте автоматически. Ответ — F1 («за») и F2 («против»); эти клавиши перехватываются, пока окно открыто. Несколько голосований встают в очередь и показываются по одному.