From f063fa7cd72b493d9b101e6e0ed855dd960792d6 Mon Sep 17 00:00:00 2001
From: harryob <55142896+harryob@users.noreply.github.com>
Date: Thu, 21 Nov 2024 16:06:20 +0000
Subject: [PATCH 1/6] adds poll subsystem, entities and ui
---
code/controllers/subsystem/polls.dm | 317 ++++++++++++++++++++++
code/modules/mob/new_player/new_player.dm | 4 +
colonialmarines.dme | 1 +
tgui/packages/tgui/interfaces/Poll.tsx | 132 +++++++++
4 files changed, 454 insertions(+)
create mode 100644 code/controllers/subsystem/polls.dm
create mode 100644 tgui/packages/tgui/interfaces/Poll.tsx
diff --git a/code/controllers/subsystem/polls.dm b/code/controllers/subsystem/polls.dm
new file mode 100644
index 000000000000..c34a9d17049d
--- /dev/null
+++ b/code/controllers/subsystem/polls.dm
@@ -0,0 +1,317 @@
+SUBSYSTEM_DEF(polls)
+ name = "Polls"
+
+ var/list/datum/poll/active_polls
+ var/list/datum/poll/concluded_polls
+
+/datum/controller/subsystem/polls/Initialize()
+ setup_polls()
+
+ return SS_INIT_SUCCESS
+
+/// Clear and populate the poll lists with fresh data
+/datum/controller/subsystem/polls/proc/setup_polls()
+ active_polls = list()
+
+ var/list/datum/view_record/poll/all_active_polls = DB_VIEW(
+ /datum/view_record/poll,
+ DB_AND(
+ DB_COMP("active", DB_EQUALS, TRUE),
+ DB_COMP("expiry", DB_GREATER_EQUAL, time2text(world.realtime, "YYYY-MM-DD hh:mm:ss"))
+ )
+ )
+
+ for(var/datum/view_record/poll/poll as anything in all_active_polls)
+ var/datum/poll/new_poll = new(poll.question)
+
+ var/list/datum/view_record/poll_answer/poll_answers = DB_VIEW(
+ /datum/view_record/poll_answer,
+ DB_COMP("poll_id", DB_EQUALS, poll.id)
+ )
+
+ for(var/datum/view_record/poll_answer/answer as anything in poll_answers)
+ new_poll.answers["[answer.id]"] = answer.answer
+
+ active_polls["[poll.id]"] = new_poll
+
+ concluded_polls = list()
+
+ var/list/datum/view_record/poll/all_concluded_polls = DB_VIEW(
+ /datum/view_record/poll,
+ DB_AND(
+ DB_COMP("active", DB_EQUALS, TRUE),
+ DB_COMP("expiry", DB_LESS, time2text(world.realtime, "YYYY-MM-DD hh:mm:ss"))
+ )
+ )
+
+ for(var/datum/view_record/poll/poll as anything in all_concluded_polls)
+ var/datum/poll/concluded/concluded_poll = new(poll.question)
+
+ var/list/datum/view_record/poll_answer/poll_answers = DB_VIEW(
+ /datum/view_record/poll_answer,
+ DB_COMP("poll_id", DB_EQUALS, poll.id)
+ )
+
+ for(var/datum/view_record/poll_answer/answer as anything in poll_answers)
+ var/total = length(DB_VIEW(/datum/view_record/player_poll_answer, DB_COMP("answer_id", DB_EQUALS, answer.id)))
+
+ concluded_poll.answer_totals[answer.answer] = total
+
+ concluded_polls["[poll.id]"] = concluded_poll
+
+ update_static_data_for_all_viewers()
+
+/datum/controller/subsystem/polls/tgui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "Poll", name)
+ ui.open()
+
+/datum/controller/subsystem/polls/ui_static_data(mob/user)
+ . = ..()
+
+ .["polls"] = list()
+ for(var/id in active_polls)
+ var/datum/poll/poll = active_polls[id]
+ .["polls"] += list(
+ list("id" = id, "question" = poll.question, "answers" = poll.answers)
+ )
+
+ .["concluded_polls"] = list()
+ for(var/id in concluded_polls)
+ var/datum/poll/concluded/concluded = concluded_polls[id]
+ .["concluded_polls"] += list(
+ list("id" = id, "question" = concluded.question, "answers" = concluded.answer_totals)
+ )
+
+ .["is_poll_maker"] = CLIENT_HAS_RIGHTS(user.client, R_PERMISSIONS)
+
+/datum/controller/subsystem/polls/ui_data(mob/user)
+ . = ..()
+
+ var/datum/entity/player/player = user.client?.player_data
+ if(!player)
+ return
+
+ .["voted_polls"] = list()
+ for(var/datum/view_record/player_poll_answer/answer in DB_VIEW(/datum/view_record/player_poll_answer, DB_COMP("player_id", DB_EQUALS, player.id)))
+ .["voted_polls"] += answer.answer_id
+
+/datum/controller/subsystem/polls/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
+ . = ..()
+ if(.)
+ return
+
+ var/datum/entity/player/player = ui.user.client?.player_data
+ if(!player)
+ return
+
+ switch(action)
+ if("vote")
+ var/voting_in = params["poll_id"]
+
+ if(!isnum(text2num(voting_in)))
+ return
+
+ var/datum/poll/selected_poll = active_polls[voting_in]
+ if(!selected_poll)
+ return
+
+ var/selected_answer = params["answer_id"]
+ if(!isnum(text2num(selected_answer)) || !selected_poll.answers[selected_answer])
+ return
+
+ var/list/datum/view_record/player_poll_answer/existing_votes = DB_VIEW(
+ /datum/view_record/player_poll_answer,
+ DB_AND(
+ DB_COMP("player_id", DB_EQUALS, player.id),
+ DB_COMP("poll_id", DB_EQUALS, text2num(voting_in))
+ )
+ )
+
+ if(length(existing_votes))
+ if(tgui_alert(ui.user, "Change existing vote?", "Change Vote", list("Yes", "No")) != "Yes")
+ return
+
+ for(var/datum/view_record/player_poll_answer/existing_vote as anything in existing_votes)
+ var/datum/entity/player_poll_answer/answer = DB_ENTITY(/datum/entity/player_poll_answer, existing_vote.id)
+ answer.sync()
+
+ answer.answer_id = text2num(selected_answer)
+ answer.save()
+ return
+
+ var/datum/entity/player_poll_answer/answer = DB_ENTITY(/datum/entity/player_poll_answer)
+ answer.player_id = player.id
+ answer.answer_id = text2num(selected_answer)
+ answer.poll_id = text2num(voting_in)
+ answer.save()
+ answer.detach()
+
+ if("create")
+ if(!CLIENT_HAS_RIGHTS(ui.user.client, R_PERMISSIONS))
+ return
+
+ var/poll_question = tgui_input_text(ui.user, "What's the question?", "Poll Question", encode = FALSE)
+ if(!poll_question)
+ return
+
+ var/list/answers = list()
+
+ var/answers_to_add = tgui_input_text(ui.user, "What answers should be added? Separate answers with ;", "Poll Answers", encode = FALSE, multiline = TRUE)
+ if(!answers_to_add)
+ return
+
+ answers = splittext(answers_to_add, ";")
+
+ if(length(answers) <= 1)
+ to_chat(ui.user, SPAN_WARNING("Poll creation cancelled - not enough added."))
+ return
+
+ var/expiry = tgui_input_number(ui.user, "How many days should this poll run for?", "Poll Length", 14)
+ if(!expiry || expiry <= 0)
+ return
+
+ if(tgui_alert(ui.user, "Confirm creating poll with question: '[poll_question]', answers: [english_list(answers)] and duration: [expiry] days.", "BuildAPoll", list("Confirm", "Cancel")) != "Confirm")
+ return
+
+ var/datum/entity/poll/poll = DB_ENTITY(/datum/entity/poll)
+ poll.active = TRUE
+ poll.question = poll_question
+ poll.expiry = time2text(world.realtime + (expiry * 24 HOURS), "YYYY-MM-DD hh:mm:ss")
+ poll.save()
+ poll.sync()
+
+ for(var/answer in answers)
+ var/datum/entity/poll_answer/new_answer = DB_ENTITY(/datum/entity/poll_answer)
+ new_answer.answer = answer // ...
+ new_answer.poll_id = poll.id
+ new_answer.save()
+ new_answer.sync()
+
+ to_chat(ui.user, SPAN_ALERT("Poll '[poll_question]' created successfully."))
+ setup_polls()
+
+ if("delete")
+ if(!CLIENT_HAS_RIGHTS(ui.user.client, R_PERMISSIONS))
+ return
+
+ var/to_delete = params["poll_id"]
+ if(!isnum(text2num(to_delete)))
+ return
+
+ var/datum/poll/delete_poll = active_polls[to_delete]
+ if(!delete_poll)
+ return
+
+ var/datum/entity/poll/poll = DB_ENTITY(/datum/entity/poll, text2num(to_delete))
+ poll.sync()
+
+ poll.active = FALSE
+ poll.save()
+ poll.sync()
+
+ to_chat(ui.user, SPAN_ALERT("Poll deleted."))
+
+ setup_polls()
+
+ return TRUE
+
+/datum/controller/subsystem/polls/ui_state(mob/user)
+ return GLOB.always_state
+
+/datum/poll
+ var/question
+ var/list/answers = list()
+
+/datum/poll/New(question)
+ src.question = question
+
+/datum/poll/concluded
+ var/answer_totals = list()
+
+/datum/entity/poll
+ var/question
+ var/active
+ var/expiry
+
+/datum/entity_meta/poll
+ entity_type = /datum/entity/poll
+ table_name = "polls"
+ field_types = list(
+ "question" = DB_FIELDTYPE_STRING_LARGE,
+ "active" = DB_FIELDTYPE_INT,
+ "expiry" = DB_FIELDTYPE_DATE,
+ )
+
+/datum/view_record/poll
+ var/id
+ var/question
+ var/active
+ var/expiry
+
+/datum/entity_view_meta/poll
+ root_record_type = /datum/entity/poll
+ destination_entity = /datum/view_record/poll
+ fields = list(
+ "id",
+ "question",
+ "active",
+ "expiry",
+ )
+
+/datum/entity/poll_answer
+ var/poll_id
+ var/answer
+
+/datum/entity_meta/poll_answer
+ entity_type = /datum/entity/poll_answer
+ table_name = "poll_answers"
+ field_types = list(
+ "poll_id" = DB_FIELDTYPE_BIGINT,
+ "answer" = DB_FIELDTYPE_STRING_LARGE,
+ )
+
+/datum/view_record/poll_answer
+ var/id
+ var/poll_id
+ var/answer
+
+/datum/entity_view_meta/poll_answer
+ root_record_type = /datum/entity/poll_answer
+ destination_entity = /datum/view_record/poll_answer
+ fields = list(
+ "id",
+ "poll_id",
+ "answer",
+ )
+
+/datum/entity/player_poll_answer
+ var/player_id
+ var/poll_id
+ var/answer_id
+
+/datum/entity_meta/player_poll_answer
+ entity_type = /datum/entity/player_poll_answer
+ table_name = "player_poll_answers"
+ field_types = list(
+ "player_id" = DB_FIELDTYPE_BIGINT,
+ "poll_id" = DB_FIELDTYPE_BIGINT,
+ "answer_id" = DB_FIELDTYPE_BIGINT,
+ )
+
+/datum/view_record/player_poll_answer
+ var/id
+ var/player_id
+ var/poll_id
+ var/answer_id
+
+/datum/entity_view_meta/player_poll_answer
+ root_record_type = /datum/entity/player_poll_answer
+ destination_entity = /datum/view_record/player_poll_answer
+ fields = list(
+ "id",
+ "player_id",
+ "poll_id",
+ "answer_id"
+ )
diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm
index e80538353210..99505d39c6df 100644
--- a/code/modules/mob/new_player/new_player.dm
+++ b/code/modules/mob/new_player/new_player.dm
@@ -47,6 +47,7 @@
output +="
[(client.prefs && client.prefs.real_name) ? client.prefs.real_name : client.key]"
output +="
[xeno_text]"
output += "
Tutorial
"
+ output += "View Polls
"
output += "Setup Character
"
output += "View Playtimes
"
@@ -210,6 +211,9 @@
if("tutorial")
tutorial_menu()
+ if("polls")
+ SSpolls.tgui_interact(src)
+
else
new_player_panel()
diff --git a/colonialmarines.dme b/colonialmarines.dme
index 423b66356dd5..c202153f801c 100644
--- a/colonialmarines.dme
+++ b/colonialmarines.dme
@@ -290,6 +290,7 @@
#include "code\controllers\subsystem\ping.dm"
#include "code\controllers\subsystem\playtime.dm"
#include "code\controllers\subsystem\police_clues.dm"
+#include "code\controllers\subsystem\polls.dm"
#include "code\controllers\subsystem\power.dm"
#include "code\controllers\subsystem\predships.dm"
#include "code\controllers\subsystem\profiler.dm"
diff --git a/tgui/packages/tgui/interfaces/Poll.tsx b/tgui/packages/tgui/interfaces/Poll.tsx
new file mode 100644
index 000000000000..391c8261be79
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/Poll.tsx
@@ -0,0 +1,132 @@
+import { BooleanLike } from 'common/react';
+
+import { useBackend } from '../backend';
+import {
+ Button,
+ Collapsible,
+ ProgressBar,
+ Section,
+ Stack,
+} from '../components';
+import { Window } from '../layouts';
+
+type PollType = {
+ id: number;
+ question: string;
+ answers: { [id: string]: string };
+};
+
+type ConcludedPoll = {
+ id: number;
+ question: string;
+ answers: { [answer: string]: number };
+};
+
+type PollData = {
+ polls: PollType[];
+ concluded_polls: ConcludedPoll[];
+ voted_polls: number[];
+ is_poll_maker: BooleanLike;
+};
+
+export const Poll = () => {
+ const { act, data } = useBackend();
+
+ const { polls, is_poll_maker, concluded_polls } = data;
+
+ return (
+
+
+ {!!is_poll_maker && (
+
+
+
+ )}
+ {polls.map((poll) => (
+
+ ))}
+ {polls.length === 0 && (
+ No polls are available to vote in.
+ )}
+
+ {concluded_polls.map((concludedPoll) => (
+
+ ))}
+ {concluded_polls.length === 0 && (
+ <>No polls have been concluded and are available to view.>
+ )}
+
+
+
+ );
+};
+
+const RenderConcludedPoll = (props: { readonly poll: ConcludedPoll }) => {
+ const { poll } = props;
+
+ const total = Object.values(poll.answers).reduce(
+ (prev, current) => prev + current,
+ 0,
+ );
+
+ return (
+
+
+ {Object.keys(poll.answers).map((answer) => (
+
+
+ {answer} ({poll.answers[answer]} vote
+ {poll.answers[answer] === 1 ? '' : 's'})
+
+
+ ))}
+
+
+ );
+};
+
+const RenderPoll = (props: { readonly poll: PollType }) => {
+ const { poll } = props;
+
+ const { act, data } = useBackend();
+ const { voted_polls, is_poll_maker } = data;
+
+ const votedIn =
+ Object.keys(poll.answers).filter((value) =>
+ voted_polls.includes(Number.parseInt(value, 10)),
+ ).length > 0;
+
+ return (
+ act('delete', { poll_id: poll.id })}>
+ Delete
+
+ )
+ }
+ >
+
+ {Object.keys(poll.answers).map((answerId) => (
+
+
+
+ ))}
+
+
+ );
+};
From cde36c4d47e065308b11d02c648d4f9fc2254dc5 Mon Sep 17 00:00:00 2001
From: harryob <55142896+harryob@users.noreply.github.com>
Date: Thu, 21 Nov 2024 16:13:20 +0000
Subject: [PATCH 2/6] long list lint fix
---
code/controllers/subsystem/polls.dm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/code/controllers/subsystem/polls.dm b/code/controllers/subsystem/polls.dm
index c34a9d17049d..742c9d366adc 100644
--- a/code/controllers/subsystem/polls.dm
+++ b/code/controllers/subsystem/polls.dm
@@ -313,5 +313,5 @@ SUBSYSTEM_DEF(polls)
"id",
"player_id",
"poll_id",
- "answer_id"
+ "answer_id",
)
From b0daea5f8590d0bc828f00547581bfa15f43786a Mon Sep 17 00:00:00 2001
From: harryob <55142896+harryob@users.noreply.github.com>
Date: Thu, 21 Nov 2024 16:26:58 +0000
Subject: [PATCH 3/6] set the subsystem as not firing
---
code/controllers/subsystem/polls.dm | 1 +
1 file changed, 1 insertion(+)
diff --git a/code/controllers/subsystem/polls.dm b/code/controllers/subsystem/polls.dm
index 742c9d366adc..5ab85306f333 100644
--- a/code/controllers/subsystem/polls.dm
+++ b/code/controllers/subsystem/polls.dm
@@ -1,5 +1,6 @@
SUBSYSTEM_DEF(polls)
name = "Polls"
+ flags = SS_NO_FIRE
var/list/datum/poll/active_polls
var/list/datum/poll/concluded_polls
From d2f1815433b22cf29310f2f344bad063601c0826 Mon Sep 17 00:00:00 2001
From: harryob <55142896+harryob@users.noreply.github.com>
Date: Fri, 22 Nov 2024 15:03:46 +0000
Subject: [PATCH 4/6] bother players to engage democratically
---
code/controllers/subsystem/polls.dm | 60 +++++++++++++++++++++++++++++
code/datums/soundOutput.dm | 2 -
2 files changed, 60 insertions(+), 2 deletions(-)
diff --git a/code/controllers/subsystem/polls.dm b/code/controllers/subsystem/polls.dm
index 5ab85306f333..106711b03443 100644
--- a/code/controllers/subsystem/polls.dm
+++ b/code/controllers/subsystem/polls.dm
@@ -2,12 +2,39 @@ SUBSYSTEM_DEF(polls)
name = "Polls"
flags = SS_NO_FIRE
+ /// Stores the polls that have not expired, and set as active
var/list/datum/poll/active_polls
+
+ /// Stores the polls that have expired, and set as active
var/list/datum/poll/concluded_polls
+ /// For storing messages to remind people to vote, that we do not want to get lost in the mess of a server starting
+ VAR_PRIVATE/list/datum/callback/to_send_at_lobby = list()
+
/datum/controller/subsystem/polls/Initialize()
setup_polls()
+ for(var/id in active_polls)
+ var/list/datum/view_record/player_poll_answer/completed_polls = DB_VIEW(
+ /datum/view_record/player_poll_answer,
+ DB_COMP("polL_id", DB_EQUALS, id)
+ )
+
+ var/voted_ids = list()
+ for(var/datum/view_record/player_poll_answer/answer as anything in completed_polls)
+ voted_ids += answer.player_id
+
+ var/datum/poll/active_poll = active_polls[id]
+
+ for(var/client/client as anything in GLOB.clients)
+ if(client.player_data.id in voted_ids)
+ continue
+
+ to_send_at_lobby += CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), client, SPAN_LARGE("You have not voted in the '[active_poll.question]' poll. Click here to vote."))
+
+ RegisterSignal(SSdcs, COMSIG_GLOB_MODE_PREGAME_LOBBY, PROC_REF(handle_lobby))
+ RegisterSignal(SSdcs, COMSIG_GLOB_CLIENT_LOGGED_IN, PROC_REF(handle_new_user))
+
return SS_INIT_SUCCESS
/// Clear and populate the poll lists with fresh data
@@ -62,6 +89,39 @@ SUBSYSTEM_DEF(polls)
update_static_data_for_all_viewers()
+/datum/controller/subsystem/polls/proc/handle_lobby(source)
+ SIGNAL_HANDLER
+
+ for(var/datum/callback/callback as anything in to_send_at_lobby)
+ callback.InvokeAsync()
+
+/datum/controller/subsystem/polls/proc/handle_new_user(source, client/new_client)
+ SIGNAL_HANDLER
+
+ INVOKE_ASYNC(src, PROC_REF(remind_new_user), new_client)
+
+/datum/controller/subsystem/polls/proc/remind_new_user(client/new_client)
+ set waitfor = FALSE
+
+ while(!new_client.player_data)
+ stoplag()
+
+ for(var/id in active_polls)
+ var/voted = length(DB_VIEW(
+ /datum/view_record/player_poll_answer,
+ DB_AND(
+ DB_COMP("player_id", DB_EQUALS, new_client.player_data.id),
+ DB_COMP("poll_id", DB_EQUALS, id)
+ )
+ ))
+
+ if(voted)
+ continue
+
+ var/datum/poll/active_poll = active_polls[id]
+
+ to_chat(new_client, SPAN_LARGE("You have not voted in the '[active_poll.question]' poll. Click here to vote."))
+
/datum/controller/subsystem/polls/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
diff --git a/code/datums/soundOutput.dm b/code/datums/soundOutput.dm
index cc7334d2cb98..97889adf6d92 100644
--- a/code/datums/soundOutput.dm
+++ b/code/datums/soundOutput.dm
@@ -19,8 +19,6 @@
return ..()
/datum/soundOutput/Destroy()
- UnregisterSignal(owner.mob, list(COMSIG_MOVABLE_MOVED, COMSIG_MOB_LOGOUT))
- UnregisterSignal(owner, COMSIG_CLIENT_MOB_LOGGED_IN)
owner = null
return ..()
From 4500793ab43c183acb39c09602ef27dac984a01c Mon Sep 17 00:00:00 2001
From: harryob <55142896+harryob@users.noreply.github.com>
Date: Fri, 22 Nov 2024 16:58:55 +0000
Subject: [PATCH 5/6] rename poll_answers to votes (obviously), open polls
should be on /mob Topic
---
code/controllers/subsystem/polls.dm | 63 ++++++++++++-----------
code/modules/mob/mob.dm | 2 +
code/modules/mob/new_player/new_player.dm | 5 +-
3 files changed, 36 insertions(+), 34 deletions(-)
diff --git a/code/controllers/subsystem/polls.dm b/code/controllers/subsystem/polls.dm
index 106711b03443..73f1e1803ee6 100644
--- a/code/controllers/subsystem/polls.dm
+++ b/code/controllers/subsystem/polls.dm
@@ -15,14 +15,14 @@ SUBSYSTEM_DEF(polls)
setup_polls()
for(var/id in active_polls)
- var/list/datum/view_record/player_poll_answer/completed_polls = DB_VIEW(
- /datum/view_record/player_poll_answer,
+ var/list/datum/view_record/player_poll_vote/votes = DB_VIEW(
+ /datum/view_record/player_poll_vote,
DB_COMP("polL_id", DB_EQUALS, id)
)
var/voted_ids = list()
- for(var/datum/view_record/player_poll_answer/answer as anything in completed_polls)
- voted_ids += answer.player_id
+ for(var/datum/view_record/player_poll_vote/vote as anything in votes)
+ voted_ids += vote.player_id
var/datum/poll/active_poll = active_polls[id]
@@ -30,7 +30,7 @@ SUBSYSTEM_DEF(polls)
if(client.player_data.id in voted_ids)
continue
- to_send_at_lobby += CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), client, SPAN_LARGE("You have not voted in the '[active_poll.question]' poll. Click here to vote."))
+ to_send_at_lobby += CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), client, SPAN_LARGE("You have not voted in the '[active_poll.question]' poll. Click here to vote."))
RegisterSignal(SSdcs, COMSIG_GLOB_MODE_PREGAME_LOBBY, PROC_REF(handle_lobby))
RegisterSignal(SSdcs, COMSIG_GLOB_CLIENT_LOGGED_IN, PROC_REF(handle_new_user))
@@ -81,7 +81,7 @@ SUBSYSTEM_DEF(polls)
)
for(var/datum/view_record/poll_answer/answer as anything in poll_answers)
- var/total = length(DB_VIEW(/datum/view_record/player_poll_answer, DB_COMP("answer_id", DB_EQUALS, answer.id)))
+ var/total = length(DB_VIEW(/datum/view_record/player_poll_vote, DB_COMP("answer_id", DB_EQUALS, answer.id)))
concluded_poll.answer_totals[answer.answer] = total
@@ -89,6 +89,8 @@ SUBSYSTEM_DEF(polls)
update_static_data_for_all_viewers()
+/// Sends all the queued messages when we enter the
+/// lobby mode, so the messages do not get lost
/datum/controller/subsystem/polls/proc/handle_lobby(source)
SIGNAL_HANDLER
@@ -100,6 +102,7 @@ SUBSYSTEM_DEF(polls)
INVOKE_ASYNC(src, PROC_REF(remind_new_user), new_client)
+/// Reminds new users logging in of any uncompleted polls.
/datum/controller/subsystem/polls/proc/remind_new_user(client/new_client)
set waitfor = FALSE
@@ -108,7 +111,7 @@ SUBSYSTEM_DEF(polls)
for(var/id in active_polls)
var/voted = length(DB_VIEW(
- /datum/view_record/player_poll_answer,
+ /datum/view_record/player_poll_vote,
DB_AND(
DB_COMP("player_id", DB_EQUALS, new_client.player_data.id),
DB_COMP("poll_id", DB_EQUALS, id)
@@ -120,7 +123,7 @@ SUBSYSTEM_DEF(polls)
var/datum/poll/active_poll = active_polls[id]
- to_chat(new_client, SPAN_LARGE("You have not voted in the '[active_poll.question]' poll. Click here to vote."))
+ to_chat(new_client, SPAN_LARGE("You have not voted in the '[active_poll.question]' poll. Click here to vote."))
/datum/controller/subsystem/polls/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
@@ -155,7 +158,7 @@ SUBSYSTEM_DEF(polls)
return
.["voted_polls"] = list()
- for(var/datum/view_record/player_poll_answer/answer in DB_VIEW(/datum/view_record/player_poll_answer, DB_COMP("player_id", DB_EQUALS, player.id)))
+ for(var/datum/view_record/player_poll_vote/answer in DB_VIEW(/datum/view_record/player_poll_vote, DB_COMP("player_id", DB_EQUALS, player.id)))
.["voted_polls"] += answer.answer_id
/datum/controller/subsystem/polls/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
@@ -182,8 +185,8 @@ SUBSYSTEM_DEF(polls)
if(!isnum(text2num(selected_answer)) || !selected_poll.answers[selected_answer])
return
- var/list/datum/view_record/player_poll_answer/existing_votes = DB_VIEW(
- /datum/view_record/player_poll_answer,
+ var/list/datum/view_record/player_poll_vote/existing_votes = DB_VIEW(
+ /datum/view_record/player_poll_vote,
DB_AND(
DB_COMP("player_id", DB_EQUALS, player.id),
DB_COMP("poll_id", DB_EQUALS, text2num(voting_in))
@@ -194,20 +197,20 @@ SUBSYSTEM_DEF(polls)
if(tgui_alert(ui.user, "Change existing vote?", "Change Vote", list("Yes", "No")) != "Yes")
return
- for(var/datum/view_record/player_poll_answer/existing_vote as anything in existing_votes)
- var/datum/entity/player_poll_answer/answer = DB_ENTITY(/datum/entity/player_poll_answer, existing_vote.id)
- answer.sync()
+ for(var/datum/view_record/player_poll_vote/existing_vote as anything in existing_votes)
+ var/datum/entity/player_poll_vote/vote = DB_ENTITY(/datum/entity/player_poll_vote, existing_vote.id)
+ vote.sync()
- answer.answer_id = text2num(selected_answer)
- answer.save()
+ vote.answer_id = text2num(selected_answer)
+ vote.save()
return
- var/datum/entity/player_poll_answer/answer = DB_ENTITY(/datum/entity/player_poll_answer)
- answer.player_id = player.id
- answer.answer_id = text2num(selected_answer)
- answer.poll_id = text2num(voting_in)
- answer.save()
- answer.detach()
+ var/datum/entity/player_poll_vote/vote = DB_ENTITY(/datum/entity/player_poll_vote)
+ vote.player_id = player.id
+ vote.answer_id = text2num(selected_answer)
+ vote.poll_id = text2num(voting_in)
+ vote.save()
+ vote.detach()
if("create")
if(!CLIENT_HAS_RIGHTS(ui.user.client, R_PERMISSIONS))
@@ -347,29 +350,29 @@ SUBSYSTEM_DEF(polls)
"answer",
)
-/datum/entity/player_poll_answer
+/datum/entity/player_poll_vote
var/player_id
var/poll_id
var/answer_id
-/datum/entity_meta/player_poll_answer
- entity_type = /datum/entity/player_poll_answer
- table_name = "player_poll_answers"
+/datum/entity_meta/player_poll_vote
+ entity_type = /datum/entity/player_poll_vote
+ table_name = "player_poll_votes"
field_types = list(
"player_id" = DB_FIELDTYPE_BIGINT,
"poll_id" = DB_FIELDTYPE_BIGINT,
"answer_id" = DB_FIELDTYPE_BIGINT,
)
-/datum/view_record/player_poll_answer
+/datum/view_record/player_poll_vote
var/id
var/player_id
var/poll_id
var/answer_id
-/datum/entity_view_meta/player_poll_answer
- root_record_type = /datum/entity/player_poll_answer
- destination_entity = /datum/view_record/player_poll_answer
+/datum/entity_view_meta/player_poll_vote
+ root_record_type = /datum/entity/player_poll_vote
+ destination_entity = /datum/view_record/player_poll_vote
fields = list(
"id",
"player_id",
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 712bef37afad..2506e321ce1a 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -985,6 +985,8 @@ note dizziness decrements automatically in the mob's Life() proc.
if(client)
client.prefs.process_link(src, href_list)
return TRUE
+ if(href_list["poll"])
+ SSpolls.tgui_interact(src)
/mob/proc/reset_perspective(atom/A)
if(!client)
diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm
index c54cff993b42..abebf84e5904 100644
--- a/code/modules/mob/new_player/new_player.dm
+++ b/code/modules/mob/new_player/new_player.dm
@@ -47,7 +47,7 @@
output +="
[(client.prefs && client.prefs.real_name) ? client.prefs.real_name : client.key]"
output +="
[xeno_text]"
output += "Tutorial
"
- output += "View Polls
"
+ output += "View Polls
"
output += "Setup Character
"
output += "View Playtimes
"
@@ -226,9 +226,6 @@
if("tutorial")
tutorial_menu()
- if("polls")
- SSpolls.tgui_interact(src)
-
else
new_player_panel()
From ddd2f66fd9ee60f828928d4bd2ca3f2cdb9ced1a Mon Sep 17 00:00:00 2001
From: harryob <55142896+harryob@users.noreply.github.com>
Date: Thu, 30 Jan 2025 15:59:25 +0000
Subject: [PATCH 6/6] firaviews
---
code/controllers/subsystem/polls.dm | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/code/controllers/subsystem/polls.dm b/code/controllers/subsystem/polls.dm
index 73f1e1803ee6..c0ebdd932ee8 100644
--- a/code/controllers/subsystem/polls.dm
+++ b/code/controllers/subsystem/polls.dm
@@ -100,14 +100,13 @@ SUBSYSTEM_DEF(polls)
/datum/controller/subsystem/polls/proc/handle_new_user(source, client/new_client)
SIGNAL_HANDLER
- INVOKE_ASYNC(src, PROC_REF(remind_new_user), new_client)
+ remind_new_user(new_client)
/// Reminds new users logging in of any uncompleted polls.
/datum/controller/subsystem/polls/proc/remind_new_user(client/new_client)
set waitfor = FALSE
- while(!new_client.player_data)
- stoplag()
+ UNTIL(new_client.player_data)
for(var/id in active_polls)
var/voted = length(DB_VIEW(