diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index 13764cb9b50..8b96a5491bd 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -871,7 +871,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." set_never_round() return if(LAZYACCESS(modifiers, CTRL_CLICK) && poll.jump_to_me) - jump_to_pic_source() + jump_to_jump_target() return handle_sign_up() @@ -891,7 +891,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." poll.undo_never_for_this_round(owner) color = initial(color) -/atom/movable/screen/alert/poll_alert/proc/jump_to_pic_source() +/atom/movable/screen/alert/poll_alert/proc/jump_to_jump_target() if(!poll?.jump_to_me || !isobserver(owner)) return var/turf/target_turf = get_turf(poll.jump_to_me) @@ -905,7 +905,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." if(href_list["signup"]) handle_sign_up() if(href_list["jump"]) - jump_to_pic_source() + jump_to_jump_target() return /atom/movable/screen/alert/poll_alert/proc/update_signed_up_overlay() diff --git a/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm b/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm index 79e47cb3b3d..6c0db374f8a 100644 --- a/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm +++ b/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm @@ -144,11 +144,11 @@ SSdynamic.log_dynamic_and_announce("Polling [possible_volunteers.len] players to apply for the [name] ruleset.") candidates = SSpolling.poll_ghost_candidates( - question = "Looking for volunteers to become [antag_flag] for [name]", + question = "Looking for volunteers to become [span_notice(antag_flag)] for [span_danger(name)]", check_jobban = antag_flag_override, role = antag_flag || antag_flag_override, poll_time = 30 SECONDS, - pic_source = signup_item_path, + alert_pic = signup_item_path, role_name_text = antag_flag, ) diff --git a/code/controllers/subsystem/polling.dm b/code/controllers/subsystem/polling.dm index 038050cfb7d..110968cfcae 100644 --- a/code/controllers/subsystem/polling.dm +++ b/code/controllers/subsystem/polling.dm @@ -27,10 +27,14 @@ SUBSYSTEM_DEF(polling) * * ignore_category: Optional, A poll category. If a candidate has this category in their ignore list, they won't be polled. * * flash_window: If TRUE, the candidate's window will flash when they're polled. * * list/group: A list of candidates to poll. - * * pic_source: Optional, An /atom or an /image to display on the poll alert. + * * alert_pic: Optional, An /atom or an /image to display on the poll alert. + * * jump_target: An /atom to teleport/jump to, if alert_pic is an /atom defaults to that. * * role_name_text: Optional, A string to display in logging / the (default) question. If null, the role name will be used. * * list/custom_response_messages: Optional, A list of strings to use as responses to the poll. If null, the default responses will be used. see __DEFINES/polls.dm for valid keys to use. * * start_signed_up: If TRUE, all candidates will start signed up for the poll, making it opt-out rather than opt-in. + * * amount_to_pick: Lets you pick candidates and return a single mob or list of mobs that were chosen. + * * chat_text_border_icon: Object or path to make an icon of to decorate the chat announcement. + * * announce_chosen: Whether we should announce the chosen candidates in chat. This is ignored unless amount_to_pick is greater than 0. * * Returns a list of all mobs who signed up for the poll. */ @@ -42,18 +46,21 @@ SUBSYSTEM_DEF(polling) ignore_category = null, flash_window = TRUE, list/group = null, - pic_source, + alert_pic, + jump_target, role_name_text, list/custom_response_messages, start_signed_up = FALSE, + amount_to_pick = 0, + chat_text_border_icon, + announce_chosen = TRUE, ) - RETURN_TYPE(/list/mob) if(group.len == 0) - return list() + return if(role && !role_name_text) role_name_text = role if(role_name_text && !question) - question = "Do you want to play as [full_capitalize(role_name_text)]?" + question = "Do you want to play as [span_notice(role_name_text)]?" if(!question) question = "Do you want to play as a special role?" log_game("Polling candidates [role_name_text ? "for [role_name_text]" : "\"[question]\""] for [DisplayTimeText(poll_time)] seconds") @@ -61,9 +68,10 @@ SUBSYSTEM_DEF(polling) // Start firing total_polls++ - var/jumpable = isatom(pic_source) ? pic_source : null + if(!jump_target && isatom(alert_pic)) + jump_target = alert_pic - var/datum/candidate_poll/new_poll = new(role_name_text, question, poll_time, ignore_category, jumpable, custom_response_messages) + var/datum/candidate_poll/new_poll = new(role_name_text, question, poll_time, ignore_category, jump_target, custom_response_messages) LAZYADD(currently_polling, new_poll) var/category = "[new_poll.poll_key]_poll_alert" @@ -121,83 +129,130 @@ SUBSYSTEM_DEF(polling) break // Image to display - var/image/poll_image - if(pic_source) - if(!ispath(pic_source)) - var/atom/the_pic_source = pic_source - var/old_layer = the_pic_source.layer - var/old_plane = the_pic_source.plane - the_pic_source.plane = poll_alert_button.plane - the_pic_source.layer = FLOAT_LAYER - poll_alert_button.add_overlay(the_pic_source) - the_pic_source.layer = old_layer - the_pic_source.plane = old_plane + var/image/poll_image = image('icons/effects/effects.dmi', icon_state = "static") + if(alert_pic) + if(!ispath(alert_pic)) + var/mutable_appearance/picture_source = alert_pic + poll_image = picture_source else - poll_image = image(pic_source, layer = FLOAT_LAYER) - else - // Just use a generic image - poll_image = image('icons/effects/effects.dmi', icon_state = "static", layer = FLOAT_LAYER) + poll_image = image(alert_pic) if(poll_image) + poll_image.layer = FLOAT_LAYER poll_image.plane = poll_alert_button.plane poll_alert_button.add_overlay(poll_image) // Chat message var/act_jump = "" - if(isatom(pic_source) && isobserver(candidate_mob)) - act_jump = "\[Teleport\]" - var/act_signup = "\[[start_signed_up ? "Opt out" : "Sign Up"]\]" + var/custom_link_style_start = "" + var/custom_link_style_end = "style='color:DodgerBlue;font-weight:bold;-dm-text-outline: 1px black'" + if(isatom(alert_pic) && isobserver(candidate_mob)) + act_jump = "[custom_link_style_start]\[Teleport\]" + var/act_signup = "[custom_link_style_start]\[[start_signed_up ? "Opt out" : "Sign Up"]\]" var/act_never = "" if(ignore_category) - act_never = "\[Never For This Round\]" + act_never = "[custom_link_style_start]\[Never For This Round\]" if(!duplicate_message_check(alert_poll)) //Only notify people once. They'll notice if there are multiple and we don't want to spam people. SEND_SOUND(candidate_mob, 'sound/misc/notice2.ogg') - to_chat(candidate_mob, span_boldnotice(examine_block("Now looking for candidates [role_name_text ? "to play as \an [role_name_text]." : "\"[question]\""] [act_jump] [act_signup] [act_never]"))) + var/surrounding_icon + if(chat_text_border_icon) + var/image/surrounding_image + if(!ispath(chat_text_border_icon)) + var/mutable_appearance/border_image = chat_text_border_icon + surrounding_image = border_image + else + surrounding_image = image(chat_text_border_icon) + surrounding_icon = icon2html(surrounding_image, candidate_mob, extra_classes = "bigicon") + var/final_message = examine_block("[surrounding_icon] [span_ooc(question)] [surrounding_icon]\n[act_jump] [act_signup] [act_never]") + to_chat(candidate_mob, final_message) // Start processing it so it updates visually the timer START_PROCESSING(SSprocessing, poll_alert_button) // Sleep until the time is up UNTIL(new_poll.finished) - return new_poll.signed_up - -/datum/controller/subsystem/polling/proc/poll_ghost_candidates(question, role, check_jobban, poll_time = 30 SECONDS, ignore_category = null, flashwindow = TRUE, pic_source, role_name_text) + if(!(amount_to_pick > 0)) + return new_poll.signed_up + for(var/pick in 1 to amount_to_pick) + new_poll.chosen_candidates += pick_n_take(new_poll.signed_up) + if(announce_chosen) + new_poll.announce_chosen(group) + if(new_poll.chosen_candidates.len == 1) + var/chosen_one = pick(new_poll.chosen_candidates) + return chosen_one + return new_poll.chosen_candidates + +/datum/controller/subsystem/polling/proc/poll_ghost_candidates( + question, + role, + check_jobban, + poll_time = 30 SECONDS, + ignore_category = null, + flashwindow = TRUE, + alert_pic, + jump_target, + role_name_text, + list/custom_response_messages, + start_signed_up = FALSE, + amount_to_pick = 0, + chat_text_border_icon, + announce_chosen = TRUE, +) var/list/candidates = list() if(!(GLOB.ghost_role_flags & GHOSTROLE_STATION_SENTIENCE)) - return candidates - + return for(var/mob/dead/observer/ghost_player in GLOB.player_list) candidates += ghost_player + return poll_candidates(question, role, check_jobban, poll_time, ignore_category, flashwindow, candidates, alert_pic, jump_target, role_name_text, custom_response_messages, start_signed_up, amount_to_pick, chat_text_border_icon, announce_chosen) - return poll_candidates(question, role, check_jobban, poll_time, ignore_category, flashwindow, candidates, pic_source, role_name_text) - -/datum/controller/subsystem/polling/proc/poll_ghost_candidates_for_mob(question, role, check_jobban, poll_time = 30 SECONDS, mob/target_mob, ignore_category = null, flashwindow = TRUE, pic_source, role_name_text) - var/static/list/mob/currently_polling_mobs = list() - - if(currently_polling_mobs.Find(target_mob)) - return list() - - currently_polling_mobs += target_mob - - var/list/possible_candidates = poll_ghost_candidates(question, role, check_jobban, poll_time, ignore_category, flashwindow, pic_source, role_name_text) - - currently_polling_mobs -= target_mob - if(!target_mob || QDELETED(target_mob) || !target_mob.loc) - return list() - - return possible_candidates - -/datum/controller/subsystem/polling/proc/poll_ghost_candidates_for_mobs(question, role, check_jobban, poll_time = 30 SECONDS, list/mobs, ignore_category = null, pic_source, role_name_text) - var/list/candidate_list = poll_ghost_candidates(question, role, check_jobban, poll_time, ignore_category, pic_source, role_name_text) - - for(var/mob/potential_mob as anything in mobs) - if(QDELETED(potential_mob) || !potential_mob.loc) - mobs -= potential_mob - - if(!length(mobs)) +/datum/controller/subsystem/polling/proc/poll_ghosts_for_target( + question, + role, + check_jobban, + poll_time = 30 SECONDS, + atom/movable/checked_target, + ignore_category = null, + flashwindow = TRUE, + alert_pic, + jump_target, + role_name_text, + list/custom_response_messages, + start_signed_up = FALSE, + chat_text_border_icon, + announce_chosen = TRUE, +) + var/static/list/atom/movable/currently_polling_targets = list() + if(currently_polling_targets.Find(checked_target)) + return + currently_polling_targets += checked_target + var/mob/chosen_one = poll_ghost_candidates(question, role, check_jobban, poll_time, ignore_category, flashwindow, alert_pic, jump_target, role_name_text, custom_response_messages, start_signed_up, amount_to_pick = 1, chat_text_border_icon = chat_text_border_icon, announce_chosen = announce_chosen) + currently_polling_targets -= checked_target + if(!checked_target || QDELETED(checked_target) || !checked_target.loc) + return null + return chosen_one + +/datum/controller/subsystem/polling/proc/poll_ghosts_for_targets( + question, + role, + check_jobban, + poll_time = 30 SECONDS, + list/checked_targets, + ignore_category = null, + flashwindow = TRUE, + alert_pic, + jump_target, + role_name_text, + list/custom_response_messages, + start_signed_up = FALSE, + chat_text_border_icon, +) + var/list/candidate_list = poll_ghost_candidates(question, role, check_jobban, poll_time, ignore_category, flashwindow, alert_pic, jump_target, role_name_text, custom_response_messages, start_signed_up, chat_text_border_icon = chat_text_border_icon) + for(var/atom/movable/potential_target as anything in checked_targets) + if(QDELETED(potential_target) || !potential_target.loc) + checked_targets -= potential_target + if(!length(checked_targets)) return list() - return candidate_list /datum/controller/subsystem/polling/proc/is_eligible(mob/potential_candidate, role, check_jobban, the_ignore_category) diff --git a/code/datums/brain_damage/imaginary_friend.dm b/code/datums/brain_damage/imaginary_friend.dm index 664bf50fd66..29cf637a86e 100644 --- a/code/datums/brain_damage/imaginary_friend.dm +++ b/code/datums/brain_damage/imaginary_friend.dm @@ -45,15 +45,18 @@ /datum/brain_trauma/special/imaginary_friend/proc/make_friend() friend = new(get_turf(owner), owner) -/// Tries an orbit poll for the imaginary friend +/// Tries a poll for the imaginary friend /datum/brain_trauma/special/imaginary_friend/proc/get_ghost() - var/datum/callback/to_call = CALLBACK(src, PROC_REF(add_friend)) - owner.AddComponent(/datum/component/orbit_poll, \ - ignore_key = POLL_IGNORE_IMAGINARYFRIEND, \ - job_bans = ROLE_PAI, \ - title = "[owner.real_name]'s imaginary friend", \ - to_call = to_call, \ + var/mob/chosen_one = SSpolling.poll_ghosts_for_target( + question = "Do you want to play as [span_danger("[owner.real_name]'s")] [span_notice("imaginary friend")]?", + check_jobban = ROLE_PAI, + poll_time = 20 SECONDS, + checked_target = owner, + ignore_category = POLL_IGNORE_IMAGINARYFRIEND, + alert_pic = owner, + role_name_text = "imaginary friend", ) + add_friend(chosen_one) /// Yay more friends! /datum/brain_trauma/special/imaginary_friend/proc/add_friend(mob/dead/observer/ghost) diff --git a/code/datums/brain_damage/split_personality.dm b/code/datums/brain_damage/split_personality.dm index f6e83c9537c..adad6491cf4 100644 --- a/code/datums/brain_damage/split_personality.dm +++ b/code/datums/brain_damage/split_personality.dm @@ -34,13 +34,16 @@ /// Attempts to get a ghost to play the personality /datum/brain_trauma/severe/split_personality/proc/get_ghost() - var/datum/callback/to_call = CALLBACK(src, PROC_REF(schism)) - owner.AddComponent(/datum/component/orbit_poll, \ - ignore_key = POLL_IGNORE_SPLITPERSONALITY, \ - job_bans = ROLE_PAI, \ - title = "[owner.real_name]'s [poll_role]", \ - to_call = to_call, \ + var/mob/chosen_one = SSpolling.poll_ghosts_for_target( + question = "Do you want to play as [span_danger("[owner.real_name]'s")] [span_notice(poll_role)]?", + check_jobban = ROLE_PAI, + poll_time = 20 SECONDS, + checked_target = owner, + ignore_category = POLL_IGNORE_SPLITPERSONALITY, + alert_pic = owner, + role_name_text = poll_role, ) + schism(chosen_one) /// Ghost poll has concluded /datum/brain_trauma/severe/split_personality/proc/schism(mob/dead/observer/ghost) @@ -211,10 +214,9 @@ /datum/brain_trauma/severe/split_personality/brainwashing/get_ghost() set waitfor = FALSE - var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates_for_mob("Do you want to play as [owner.real_name]'s brainwashed mind?", poll_time = 7.5 SECONDS, target_mob = stranger_backseat, pic_source = owner, role_name_text = "brainwashed mind") - if(LAZYLEN(candidates)) - var/mob/dead/observer/C = pick(candidates) - stranger_backseat.key = C.key + var/mob/chosen_one = SSpolling.poll_ghosts_for_target("Do you want to play as [span_danger("[owner.real_name]'s")] brainwashed mind?", poll_time = 7.5 SECONDS, checked_target = stranger_backseat, alert_pic = owner, role_name_text = "brainwashed mind") + if(chosen_one) + stranger_backseat.key = chosen_one.key else qdel(src) diff --git a/code/datums/candidate_poll.dm b/code/datums/candidate_poll.dm index 6ccd43c01fd..fc86d70f546 100644 --- a/code/datums/candidate_poll.dm +++ b/code/datums/candidate_poll.dm @@ -28,6 +28,7 @@ POLL_RESPONSE_TOO_LATE_TO_UNREGISTER = "It's too late to unregister yourself, selection has already begun!", POLL_RESPONSE_UNREGISTERED = "You have been unregistered as a candidate for %ROLE%. You can sign up again before the poll ends.", ) + var/list/chosen_candidates = list() /datum/candidate_poll/New( polled_role, @@ -131,3 +132,14 @@ /datum/candidate_poll/proc/time_left() return duration - (world.time - time_started) + + +/// Print to chat which candidate was selected +/datum/candidate_poll/proc/announce_chosen(list/poll_recipients) + if(!length(chosen_candidates)) + return + for(var/mob/poll_recipient as anything in poll_recipients) + for(var/mob/chosen as anything in chosen_candidates) + if(isnull(chosen)) + continue + to_chat(poll_recipient, span_ooc("[isobserver(poll_recipient) ? FOLLOW_LINK(poll_recipient, chosen) : null][span_warning(" [full_capitalize(role)] Poll: ")][key_name(chosen, include_name = FALSE)] was selected.")) diff --git a/code/datums/components/ghost_direct_control.dm b/code/datums/components/ghost_direct_control.dm index a131a2d3ca7..de5bca4fcad 100644 --- a/code/datums/components/ghost_direct_control.dm +++ b/code/datums/components/ghost_direct_control.dm @@ -16,8 +16,11 @@ /datum/component/ghost_direct_control/Initialize( ban_type = ROLE_SENTIENCE, role_name = null, + poll_question = null, poll_candidates = TRUE, + poll_announce_chosen = TRUE, poll_length = 10 SECONDS, + poll_chat_border_icon = null, poll_ignore_key = POLL_IGNORE_SENTIENCE_POTION, assumed_control_message = null, datum/callback/extra_control_checks, @@ -36,7 +39,7 @@ LAZYADD(GLOB.joinable_mobs[format_text("[initial(mob_parent.name)]")], mob_parent) if (poll_candidates) - INVOKE_ASYNC(src, PROC_REF(request_ghost_control), role_name || "[parent]", poll_length, poll_ignore_key) + INVOKE_ASYNC(src, PROC_REF(request_ghost_control), poll_question, role_name || "[parent]", poll_length, poll_ignore_key, poll_announce_chosen, poll_chat_border_icon) /datum/component/ghost_direct_control/RegisterWithParent() . = ..() @@ -70,23 +73,26 @@ examine_text += span_boldnotice("You could take control of this mob by clicking on it.") /// Send out a request for a brain -/datum/component/ghost_direct_control/proc/request_ghost_control(role_name, poll_length, poll_ignore_key) - if (!(GLOB.ghost_role_flags & GHOSTROLE_SPAWNER)) +/datum/component/ghost_direct_control/proc/request_ghost_control(poll_question, role_name, poll_length, poll_ignore_key, poll_announce_chosen, poll_chat_border_icon) + if(!(GLOB.ghost_role_flags & GHOSTROLE_SPAWNER)) return awaiting_ghosts = TRUE - var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates( - question = "Do you want to play as [role_name]?", + var/mob/chosen_one = SSpolling.poll_ghosts_for_target( + question = poll_question, check_jobban = ban_type, role = ban_type, poll_time = poll_length, + checked_target = parent, ignore_category = poll_ignore_key, - pic_source = parent, + alert_pic = parent, role_name_text = role_name, + chat_text_border_icon = poll_chat_border_icon, + announce_chosen = poll_announce_chosen, ) awaiting_ghosts = FALSE - if (!LAZYLEN(candidates)) + if(isnull(chosen_one)) return - assume_direct_control(pick(candidates)) + assume_direct_control(chosen_one) /// A ghost clicked on us, they want to get in this body /datum/component/ghost_direct_control/proc/on_ghost_clicked(mob/our_mob, mob/dead/observer/hopeful_ghost) diff --git a/code/datums/components/orbit_poll.dm b/code/datums/components/orbit_poll.dm deleted file mode 100644 index ceb85d16d64..00000000000 --- a/code/datums/components/orbit_poll.dm +++ /dev/null @@ -1,133 +0,0 @@ -/** - * A replacement for the standard poll_ghost_candidate. - * Use this to subtly ask players to join - it picks from orbiters. - * Please use named arguments for this. - * - * @params ignore_key - Required so it doesn't spam - * @params job_bans - You can insert a list or single items here. - * @params cb - Invokes this proc and appends the poll winner as the last argument, mob/dead/observer/ghost - * @params title - Optional. Useful if the role name does not match the parent. - * - * @usage - * ``` - * var/datum/callback/cb = CALLBACK(src, PROC_REF(do_stuff), arg1, arg2) - * AddComponent(/datum/component/orbit_poll, \ - * ignore_key = POLL_IGNORE_EXAMPLE, \ - * job_bans = ROLE_EXAMPLE or list(ROLE_EXAMPLE, ROLE_EXAMPLE2), \ - * title = "Use this if you want something other than the parent name", \ - * to_call = cb, \ - * ) - */ -/datum/component/orbit_poll - /// Prevent players with this ban from being selected - var/list/job_bans = list() - /// Title of the role to announce after it's done - var/title - /// Proc to invoke whenever the poll is complete - var/datum/callback/to_call - -/datum/component/orbit_poll/Initialize( \ - ignore_key, \ - list/job_bans, \ - datum/callback/to_call, \ - title, \ - header = "Ghost Poll", \ - custom_message, \ - timeout = 20 SECONDS \ -) - . = ..() - if (!isatom(parent)) - return COMPONENT_INCOMPATIBLE - - var/atom/owner = parent - - src.job_bans |= job_bans - src.title = title || owner.name - src.to_call = to_call - - var/message = custom_message || "[capitalize(src.title)] is looking for volunteers" - - notify_ghosts( - "[message]. An orbiter will be chosen in [DisplayTimeText(timeout)].\n", - source = parent, - header = "Volunteers requested", - custom_link = " (Ignore)", - ignore_key = ignore_key, - notify_flags = NOTIFY_CATEGORY_NOFLASH, - ) - - addtimer(CALLBACK(src, PROC_REF(end_poll)), timeout, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_STOPPABLE|TIMER_DELETE_ME) - -/datum/component/orbit_poll/Topic(href, list/href_list) - if(!href_list["ignore"]) - return - - var/mob/user = usr - - var/ignore_key = href_list["ignore"] - if(tgui_alert(user, "Ignore further [title] alerts?", "Ignore Alert", list("Yes", "No"), 20 SECONDS, TRUE) != "Yes") - return - - GLOB.poll_ignore[ignore_key] |= user.ckey - -/// Concludes the poll, picking one of the orbiters -/datum/component/orbit_poll/proc/end_poll() - if(QDELETED(parent)) - return - - var/list/candidates = list() - var/atom/owner = parent - - var/datum/component/orbiter/orbiter_comp = owner.GetComponent(/datum/component/orbiter) - if(isnull(orbiter_comp)) - phone_home() - return - - for(var/mob/dead/observer/ghost as anything in orbiter_comp.orbiter_list) - var/client/ghost_client = ghost.client - - if(QDELETED(ghost) || isnull(ghost_client)) - continue - - if(is_banned_from(ghost.ckey, job_bans)) - continue - - var/datum/preferences/ghost_prefs = ghost_client.prefs - if(isnull(ghost_prefs)) - candidates += ghost // we'll assume they wanted to be picked despite prefs being null for whatever fucked up reason - continue - - if(!ghost_prefs.read_preference(/datum/preference/toggle/ghost_roles)) - continue - if(!isnull(ghost_client.holder) && !ghost_prefs.read_preference(/datum/preference/toggle/ghost_roles_as_admin)) - continue - - candidates += ghost - - pick_and_offer(candidates) - -/// Takes a list, picks a candidate, and offers the role to them. -/datum/component/orbit_poll/proc/pick_and_offer(list/volunteers) - if(length(volunteers) <= 0) - phone_home() - return - - var/mob/dead/observer/chosen = pick(volunteers) - - if(isnull(chosen)) - phone_home() - return - - SEND_SOUND(chosen, 'sound/misc/notice2.ogg') - var/response = tgui_alert(chosen, "Do you want to assume the role of [title]?", "Orbit Polling", list("Yes", "No"), 10 SECONDS) - if(response != "Yes") - var/reusable_list = volunteers - chosen - return pick_and_offer(reusable_list) - - deadchat_broadcast("[key_name(chosen, include_name = FALSE)] was selected for the role ([title]).", "Ghost Poll: ", parent) - phone_home(chosen) - -/// Make sure to call your parents my dude -/datum/component/orbit_poll/proc/phone_home(mob/dead/observer/chosen) - to_call.Invoke(chosen) - qdel(src) diff --git a/code/datums/components/spirit_holding.dm b/code/datums/components/spirit_holding.dm index cb626801d86..e2b1cfb96bc 100644 --- a/code/datums/components/spirit_holding.dm +++ b/code/datums/components/spirit_holding.dm @@ -37,9 +37,10 @@ ///signal fired on self attacking parent /datum/component/spirit_holding/proc/on_attack_self(datum/source, mob/user) SIGNAL_HANDLER + INVOKE_ASYNC(src, PROC_REF(get_ghost), user) +/datum/component/spirit_holding/proc/get_ghost(mob/user) var/atom/thing = parent - if(attempting_awakening) thing.balloon_alert(user, "already channeling!") return @@ -47,20 +48,23 @@ thing.balloon_alert(user, "spirits are unwilling!") to_chat(user, span_warning("Anomalous otherworldly energies block you from awakening [parent]!")) return - attempting_awakening = TRUE thing.balloon_alert(user, "channeling...") - - var/datum/callback/to_call = CALLBACK(src, PROC_REF(affix_spirit), user) - parent.AddComponent(/datum/component/orbit_poll, \ - ignore_key = POLL_IGNORE_POSSESSED_BLADE, \ - job_bans = ROLE_PAI, \ - to_call = to_call, \ - title = "Spirit of [user.real_name]'s blade", \ + var/mob/chosen_one = SSpolling.poll_ghosts_for_target( + question = "Do you want to play as [span_notice("Spirit of [span_danger("[user.real_name]'s")] blade")]?", + check_jobban = ROLE_PAI, + poll_time = 20 SECONDS, + checked_target = thing, + ignore_category = POLL_IGNORE_POSSESSED_BLADE, + alert_pic = thing, + role_name_text = "possessed blade", + chat_text_border_icon = thing, ) + affix_spirit(user, chosen_one) /// On conclusion of the ghost poll /datum/component/spirit_holding/proc/affix_spirit(mob/awakener, mob/dead/observer/ghost) + var/atom/thing = parent if(isnull(ghost)) diff --git a/code/datums/diseases/transformation.dm b/code/datums/diseases/transformation.dm index 741520ed6ae..4cf5b4148fe 100644 --- a/code/datums/diseases/transformation.dm +++ b/code/datums/diseases/transformation.dm @@ -84,13 +84,12 @@ /datum/disease/transformation/proc/replace_banned_player(mob/living/new_mob) // This can run well after the mob has been transferred, so need a handle on the new mob to kill it if needed. set waitfor = FALSE - var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates_for_mob("Do you want to play as [affected_mob.real_name]?", check_jobban = bantype, role = bantype, poll_time = 5 SECONDS, target_mob = affected_mob, pic_source = affected_mob, role_name_text = "transformation victim") - if(LAZYLEN(candidates)) - var/mob/dead/observer/C = pick(candidates) + var/mob/chosen_one = SSpolling.poll_ghosts_for_target("Do you want to play as [span_notice(affected_mob.real_name)]?", check_jobban = bantype, role = bantype, poll_time = 5 SECONDS, checked_target = affected_mob, alert_pic = affected_mob, role_name_text = "transformation victim") + if(chosen_one) to_chat(affected_mob, span_userdanger("Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!")) - message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(affected_mob)]) to replace a jobbanned player.") + message_admins("[key_name_admin(chosen_one)] has taken control of ([key_name_admin(affected_mob)]) to replace a jobbanned player.") affected_mob.ghostize(FALSE) - affected_mob.key = C.key + affected_mob.key = chosen_one.key else to_chat(new_mob, span_userdanger("Your mob has been claimed by death! Appeal your job ban if you want to avoid this in the future!")) new_mob.investigate_log("has been killed because there was no one to replace them as a job-banned player.", INVESTIGATE_DEATHS) diff --git a/code/game/objects/effects/anomalies/anomalies_ectoplasm.dm b/code/game/objects/effects/anomalies/anomalies_ectoplasm.dm index 7a04aaf2435..412cca04952 100644 --- a/code/game/objects/effects/anomalies/anomalies_ectoplasm.dm +++ b/code/game/objects/effects/anomalies/anomalies_ectoplasm.dm @@ -178,7 +178,7 @@ candidate_list += GLOB.current_observers_list candidate_list += GLOB.dead_player_list - var/list/candidates = SSpolling.poll_candidates("Would you like to participate in a spooky ghost swarm? (Warning: you will not be able to return to your body!)", check_jobban = ROLE_SENTIENCE, poll_time = 10 SECONDS, group = candidate_list, pic_source = src, role_name_text = "ghost swarm") + var/list/candidates = SSpolling.poll_candidates("Would you like to participate in a spooky ghost swarm? (Warning: you will not be able to return to your body!)", check_jobban = ROLE_SENTIENCE, poll_time = 10 SECONDS, group = candidate_list, alert_pic = src, role_name_text = "ghost swarm") for(var/mob/dead/observer/candidate_ghost as anything in candidates) var/mob/living/basic/ghost/swarm/new_ghost = new(get_turf(src)) ghosts_spawned += new_ghost diff --git a/code/game/objects/effects/anomalies/anomalies_pyroclastic.dm b/code/game/objects/effects/anomalies/anomalies_pyroclastic.dm index 87221eeec9f..a4880fdc267 100644 --- a/code/game/objects/effects/anomalies/anomalies_pyroclastic.dm +++ b/code/game/objects/effects/anomalies/anomalies_pyroclastic.dm @@ -39,12 +39,10 @@ var/datum/action/innate/slime/reproduce/repro_action = new repro_action.Grant(pyro) - var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates_for_mob("Do you want to play as a pyroclastic anomaly slime?", check_jobban = ROLE_SENTIENCE, poll_time = 10 SECONDS, target_mob = pyro, ignore_category = POLL_IGNORE_PYROSLIME, pic_source = pyro, role_name_text = "pyroclastic anomaly slime") - if(!LAZYLEN(candidates)) + var/mob/chosen_one = SSpolling.poll_ghosts_for_target(check_jobban = ROLE_SENTIENCE, poll_time = 10 SECONDS, checked_target = pyro, ignore_category = POLL_IGNORE_PYROSLIME, alert_pic = pyro, role_name_text = "pyroclastic anomaly slime") + if(isnull(chosen_one)) return - - var/mob/dead/observer/chosen = pick(candidates) - pyro.key = chosen.key + pyro.key = chosen_one.key pyro.mind.special_role = ROLE_PYROCLASTIC_SLIME pyro.mind.add_antag_datum(/datum/antagonist/pyro_slime) pyro.log_message("was made into a slime by pyroclastic anomaly", LOG_GAME) diff --git a/code/game/objects/items/devices/aicard_evil.dm b/code/game/objects/items/devices/aicard_evil.dm index f91150bb086..8aaa9f03111 100644 --- a/code/game/objects/items/devices/aicard_evil.dm +++ b/code/game/objects/items/devices/aicard_evil.dm @@ -34,14 +34,16 @@ if(isnull(op_datum)) balloon_alert(user, "invalid access!") return - - var/datum/callback/to_call = CALLBACK(src, PROC_REF(on_poll_concluded), user, op_datum) - AddComponent(/datum/component/orbit_poll, \ - ignore_key = POLL_IGNORE_SYNDICATE, \ - job_bans = ROLE_OPERATIVE, \ - to_call = to_call, \ - title = "Nuclear Operative Modsuit AI" \ + var/mob/chosen_one = SSpolling.poll_ghosts_for_target( + check_jobban = ROLE_OPERATIVE, + poll_time = 20 SECONDS, + checked_target = src, + ignore_category = POLL_IGNORE_SYNDICATE, + alert_pic = src, + role_name_text = "Nuclear Operative Modsuit AI", + chat_text_border_icon = mutable_appearance(icon, "syndicard-full"), ) + on_poll_concluded(user, op_datum, chosen_one) /// Poll has concluded with a ghost, create the AI /obj/item/aicard/syndie/loaded/proc/on_poll_concluded(mob/user, datum/antagonist/nukeop/op_datum, mob/dead/observer/ghost) diff --git a/code/game/objects/items/dice.dm b/code/game/objects/items/dice.dm index 2ef6c4e7aa8..5777985083a 100644 --- a/code/game/objects/items/dice.dm +++ b/code/game/objects/items/dice.dm @@ -431,11 +431,10 @@ var/mob/living/carbon/human/human_servant = new(drop_location()) do_smoke(0, holder = src, location = drop_location()) - var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates_for_mob("Do you want to play as [user.real_name]'s Servant?", check_jobban = ROLE_WIZARD, role = ROLE_WIZARD, poll_time = 5 SECONDS, target_mob = human_servant, pic_source = user, role_name_text = "dice servant") - if(LAZYLEN(candidates)) - var/mob/dead/observer/candidate = pick(candidates) - message_admins("[ADMIN_LOOKUPFLW(candidate)] was spawned as Dice Servant") - human_servant.key = candidate.key + var/mob/chosen_one = SSpolling.poll_ghosts_for_target("Do you want to play as [span_danger("[user.real_name]'s")] [span_notice("Servant")]?", check_jobban = ROLE_WIZARD, role = ROLE_WIZARD, poll_time = 5 SECONDS, checked_target = human_servant, alert_pic = user, role_name_text = "dice servant") + if(chosen_one) + message_admins("[ADMIN_LOOKUPFLW(chosen_one)] was spawned as Dice Servant") + human_servant.key = chosen_one.key human_servant.equipOutfit(/datum/outfit/butler) var/datum/mind/servant_mind = new /datum/mind() diff --git a/code/modules/admin/fun_balloon.dm b/code/modules/admin/fun_balloon.dm index 4d74f542560..b65f72f8f4d 100644 --- a/code/modules/admin/fun_balloon.dm +++ b/code/modules/admin/fun_balloon.dm @@ -87,14 +87,14 @@ if (!possessable.ckey && possessable.stat == CONSCIOUS) // Only assign ghosts to living, non-occupied mobs! bodies += possessable - var/list/candidates = SSpolling.poll_ghost_candidates_for_mobs( - question = "Would you like to be [group_name]?", + var/list/candidates = SSpolling.poll_ghosts_for_targets( + question = "Would you like to be [span_notice(group_name)]?", role = ROLE_SENTIENCE, check_jobban = ROLE_SENTIENCE, poll_time = 10 SECONDS, - mobs = bodies, + checked_targets = bodies, ignore_category = POLL_IGNORE_SHUTTLE_DENIZENS, - pic_source = src, + alert_pic = src, role_name_text = "sentience fun balloon", ) diff --git a/code/modules/admin/smites/imaginary_friend_special.dm b/code/modules/admin/smites/imaginary_friend_special.dm index 5b2bc6ba805..e670e26fd1f 100644 --- a/code/modules/admin/smites/imaginary_friend_special.dm +++ b/code/modules/admin/smites/imaginary_friend_special.dm @@ -58,7 +58,6 @@ return FALSE var/list/volunteers = SSpolling.poll_ghost_candidates( - question = "Do you want to play as an imaginary friend?", check_jobban = ROLE_PAI, poll_time = 10 SECONDS, ignore_category = POLL_IGNORE_IMAGINARYFRIEND, diff --git a/code/modules/admin/verbs/ert.dm b/code/modules/admin/verbs/ert.dm index 8823acb7ef7..73b2e4d0116 100644 --- a/code/modules/admin/verbs/ert.dm +++ b/code/modules/admin/verbs/ert.dm @@ -123,7 +123,7 @@ var/list/spawnpoints = GLOB.emergencyresponseteamspawn var/index = 0 - var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates("Do you wish to be considered for [ertemplate.polldesc]?", check_jobban = "deathsquad", pic_source = /obj/item/card/id/advanced/centcom/ert, role_name_text = "emergency response team") + var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates("Do you wish to be considered for [span_notice(ertemplate.polldesc)]?", check_jobban = "deathsquad", alert_pic = /obj/item/card/id/advanced/centcom/ert, role_name_text = "emergency response team") var/teamSpawned = FALSE // This list will take priority over spawnpoints if not empty diff --git a/code/modules/admin/verbs/secrets.dm b/code/modules/admin/verbs/secrets.dm index 20a05685bc9..fa2a9fa19c6 100644 --- a/code/modules/admin/verbs/secrets.dm +++ b/code/modules/admin/verbs/secrets.dm @@ -405,7 +405,7 @@ GLOBAL_DATUM(everyone_an_antag, /datum/everyone_is_an_antag_controller) var/list/candidates = list() if (prefs["offerghosts"]["value"] == "Yes") - candidates = SSpolling.poll_ghost_candidates(replacetext(prefs["ghostpoll"]["value"], "%TYPE%", initial(pathToSpawn.name)), check_jobban = ROLE_TRAITOR, pic_source = pathToSpawn, role_name_text = "portal storm") + candidates = SSpolling.poll_ghost_candidates(replacetext(prefs["ghostpoll"]["value"], "%TYPE%", initial(pathToSpawn.name)), check_jobban = ROLE_TRAITOR, alert_pic = pathToSpawn, role_name_text = "portal storm") if (prefs["playersonly"]["value"] == "Yes" && length(candidates) < prefs["minplayers"]["value"]) message_admins("Not enough players signed up to create a portal storm, the minimum was [prefs["minplayers"]["value"]] and the number of signups [length(candidates)]") @@ -576,7 +576,7 @@ GLOBAL_DATUM(everyone_an_antag, /datum/everyone_is_an_antag_controller) if(teamsize <= 0) return FALSE - candidates = SSpolling.poll_ghost_candidates("Do you wish to be considered for a Nanotrasen emergency response drone?", check_jobban = ROLE_DRONE, pic_source = /mob/living/basic/drone/classic, role_name_text = "nanotrasen emergency response drone") + candidates = SSpolling.poll_ghost_candidates("Do you wish to be considered for a [span_notice("Nanotrasen emergency response drone")]?", check_jobban = ROLE_DRONE, alert_pic = /mob/living/basic/drone/classic, role_name_text = "nanotrasen emergency response drone") if(length(candidates) == 0) return FALSE diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm index cbcd8b0ea11..56dc650cef1 100644 --- a/code/modules/antagonists/_common/antag_datum.dm +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -293,13 +293,12 @@ GLOBAL_LIST_EMPTY(antagonists) /datum/antagonist/proc/replace_banned_player() set waitfor = FALSE - var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates_for_mob("Do you want to play as a [name]?", check_jobban = "[name]", role = job_rank, poll_time = 5 SECONDS, target_mob = owner.current, pic_source = owner.current, role_name_text = name) - if(LAZYLEN(candidates)) - var/mob/dead/observer/C = pick(candidates) + var/mob/chosen_one = SSpolling.poll_ghosts_for_target(check_jobban = job_rank, role = job_rank, poll_time = 5 SECONDS, checked_target = owner.current, alert_pic = owner.current, role_name_text = name) + if(chosen_one) to_chat(owner, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!") - message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(owner)]) to replace a jobbanned player.") + message_admins("[key_name_admin(chosen_one)] has taken control of ([key_name_admin(owner)]) to replace a jobbanned player.") owner.current.ghostize(FALSE) - owner.current.key = C.key + owner.current.key = chosen_one.key /** * Called by the remove_antag_datum() and remove_all_antag_datums() mind procs for the antag datum to handle its own removal and deletion. diff --git a/code/modules/antagonists/_common/antag_spawner.dm b/code/modules/antagonists/_common/antag_spawner.dm index 9ef40a9cebf..19ff29651ef 100644 --- a/code/modules/antagonists/_common/antag_spawner.dm +++ b/code/modules/antagonists/_common/antag_spawner.dm @@ -55,16 +55,15 @@ /obj/item/antag_spawner/contract/proc/poll_for_student(mob/living/carbon/human/teacher, apprentice_school) balloon_alert(teacher, "contacting apprentice...") polling = TRUE - var/list/candidates = SSpolling.poll_ghost_candidates_for_mob("Do you want to play as a wizard's [apprentice_school] apprentice?", check_jobban = ROLE_WIZARD, role = ROLE_WIZARD, poll_time = 15 SECONDS, target_mob = src, pic_source = teacher, role_name_text = "wizard apprentice") + var/mob/chosen_one = SSpolling.poll_ghosts_for_target("Do you want to play as [span_danger("[teacher]'s")] [span_notice("[apprentice_school] apprentice")]?", check_jobban = ROLE_WIZARD, role = ROLE_WIZARD, poll_time = 15 SECONDS, checked_target = src, alert_pic = /obj/item/clothing/head/wizard/red, jump_target = src, role_name_text = "wizard apprentice", chat_text_border_icon = /obj/item/clothing/head/wizard/red) polling = FALSE - if(!LAZYLEN(candidates)) + if(isnull(chosen_one)) to_chat(teacher, span_warning("Unable to reach your apprentice! You can either attack the spellbook with the contract to refund your points, or wait and try again later.")) return if(QDELETED(src) || used) return used = TRUE - var/mob/dead/observer/student = pick(candidates) - spawn_antag(student.client, get_turf(src), apprentice_school, teacher.mind) + spawn_antag(chosen_one.client, get_turf(src), apprentice_school, teacher.mind) /obj/item/antag_spawner/contract/spawn_antag(client/C, turf/T, kind, datum/mind/user) new /obj/effect/particle_effect/fluid/smoke(T) @@ -134,13 +133,12 @@ return to_chat(user, span_notice("You activate [src] and wait for confirmation.")) - var/list/nuke_candidates = SSpolling.poll_ghost_candidates("Do you want to play as a syndicate [borg_to_spawn ? "[lowertext(borg_to_spawn)] cyborg":"operative"]?", check_jobban = ROLE_OPERATIVE, role = ROLE_OPERATIVE, poll_time = 15 SECONDS, ignore_category = POLL_IGNORE_SYNDICATE, pic_source = src, role_name_text = "syndicate [borg_to_spawn ? "[borg_to_spawn] cyborg":"operative"]") - if(LAZYLEN(nuke_candidates)) + var/mob/chosen_one = SSpolling.poll_ghost_candidates(check_jobban = ROLE_OPERATIVE, role = ROLE_OPERATIVE, poll_time = 15 SECONDS, ignore_category = POLL_IGNORE_SYNDICATE, alert_pic = src, role_name_text = "syndicate [borg_to_spawn ? "[borg_to_spawn] cyborg":"operative"]", amount_to_pick = 1) + if(chosen_one) if(QDELETED(src) || !check_usability(user)) return used = TRUE - var/mob/dead/observer/G = pick(nuke_candidates) - spawn_antag(G.client, get_turf(src), "nukeop", user.mind) + spawn_antag(chosen_one.client, get_turf(src), "nukeop", user.mind) do_sparks(4, TRUE, src) qdel(src) else @@ -252,14 +250,13 @@ return if(used) return - var/list/candidates = SSpolling.poll_ghost_candidates_for_mob("Do you want to play as a [initial(demon_type.name)]?", check_jobban = ROLE_ALIEN, role = ROLE_ALIEN, poll_time = 5 SECONDS, target_mob = src, pic_source = src, role_name_text = initial(demon_type.name)) - if(LAZYLEN(candidates)) + var/mob/chosen_one = SSpolling.poll_ghosts_for_target(check_jobban = ROLE_ALIEN, role = ROLE_ALIEN, poll_time = 5 SECONDS, checked_target = src, alert_pic = demon_type, jump_target = src, role_name_text = initial(demon_type.name)) + if(chosen_one) if(used || QDELETED(src)) return used = TRUE - var/mob/dead/observer/summoned = pick(candidates) - user.log_message("has summoned forth the [initial(demon_type.name)] (played by [key_name(summoned)]) using a [name].", LOG_GAME) // has to be here before we create antag otherwise we can't get the ckey of the demon - spawn_antag(summoned.client, get_turf(src), initial(demon_type.name), user.mind) + user.log_message("has summoned forth the [initial(demon_type.name)] (played by [key_name(chosen_one)]) using a [name].", LOG_GAME) // has to be here before we create antag otherwise we can't get the ckey of the demon + spawn_antag(chosen_one.client, get_turf(src), initial(demon_type.name), user.mind) to_chat(user, shatter_msg) to_chat(user, veil_msg) playsound(user.loc, 'sound/effects/glassbr1.ogg', 100, TRUE) @@ -332,23 +329,22 @@ return to_chat(user, span_notice("You activate [src] and wait for confirmation.")) - var/list/baddie_candidates = SSpolling.poll_ghost_candidates( - "Do you want to play as a [role_to_play]?", + var/mob/chosen_one = SSpolling.poll_ghost_candidates( check_jobban = poll_role_check, role = poll_role_check, poll_time = 10 SECONDS, ignore_category = poll_ignore_category, - pic_source = src, + alert_pic = src, role_name_text = role_to_play, + amount_to_pick = 1 ) - if(!LAZYLEN(baddie_candidates)) + if(isnull(chosen_one)) to_chat(user, span_warning(fail_text)) return if(QDELETED(src) || !check_usability(user)) return used = TRUE - var/mob/dead/observer/ghostie = pick(baddie_candidates) - spawn_antag(ghostie.client, get_turf(src), user) + spawn_antag(chosen_one.client, get_turf(src), user) do_sparks(4, TRUE, src) qdel(src) diff --git a/code/modules/antagonists/blob/powers.dm b/code/modules/antagonists/blob/powers.dm index b35308d092f..2f3b51741f9 100644 --- a/code/modules/antagonists/blob/powers.dm +++ b/code/modules/antagonists/blob/powers.dm @@ -193,14 +193,20 @@ /mob/camera/blob/proc/pick_blobbernaut_candidate(obj/structure/blob/special/factory/factory) if(isnull(factory)) return - - var/datum/callback/to_call = CALLBACK(src, PROC_REF(on_poll_concluded), factory) - factory.AddComponent(/datum/component/orbit_poll, \ - ignore_key = POLL_IGNORE_BLOB, \ - job_bans = ROLE_BLOB, \ - to_call = to_call, \ - title = "Blobbernaut", \ + var/icon/blobbernaut_icon = icon(icon, "blobbernaut") + blobbernaut_icon.Blend(blobstrain.color, ICON_MULTIPLY) + var/image/blobbernaut_image = image(blobbernaut_icon) + var/mob/chosen_one = SSpolling.poll_ghosts_for_target( + check_jobban = ROLE_BLOB, + poll_time = 20 SECONDS, + checked_target = factory, + ignore_category = POLL_IGNORE_BLOB, + alert_pic = blobbernaut_image, + jump_target = factory, + role_name_text = "blobbernaut", + chat_text_border_icon = blobbernaut_image, ) + on_poll_concluded(factory, chosen_one) /// Called when the ghost poll concludes /mob/camera/blob/proc/on_poll_concluded(obj/structure/blob/special/factory/factory, mob/dead/observer/ghost) diff --git a/code/modules/antagonists/cult/cult_comms.dm b/code/modules/antagonists/cult/cult_comms.dm index bee8eec306f..01aac3e8691 100644 --- a/code/modules/antagonists/cult/cult_comms.dm +++ b/code/modules/antagonists/cult/cult_comms.dm @@ -147,17 +147,18 @@ asked_cultists += team_member.current var/list/yes_voters = SSpolling.poll_candidates( - question = "[nominee] seeks to lead your cult, do you support [nominee.p_them()]?", + question = "[span_notice(nominee)] seeks to lead your cult, do you support [nominee.p_them()]?", poll_time = 30 SECONDS, group = asked_cultists, - pic_source = nominee, - role_name_text = "cult master", + alert_pic = nominee, + role_name_text = "cult master nomination", custom_response_messages = list( POLL_RESPONSE_SIGNUP = "You have pledged your allegience to [nominee].", POLL_RESPONSE_ALREADY_SIGNED = "You have already pledged your allegience!", POLL_RESPONSE_NOT_SIGNED = "You aren't nominated for this.", POLL_RESPONSE_TOO_LATE_TO_UNREGISTER = "It's too late to unregister yourself, voting has already begun!", POLL_RESPONSE_UNREGISTERED = "You have been removed your pledge to [nominee].", + chat_text_border_icon = mutable_appearance('icons/effects/effects.dmi', "cult_master_logo") ) ) if(QDELETED(nominee) || nominee.incapacitated()) diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index 8d7d66979f4..8e5e7099be4 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -737,13 +737,12 @@ GLOBAL_VAR_INIT(narsie_summon_count, 0) if(!mob_to_revive.client || mob_to_revive.client.is_afk()) set waitfor = FALSE - var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates_for_mob("Do you want to play as a [mob_to_revive.real_name], an inactive blood cultist?", check_jobban = ROLE_CULTIST, role = ROLE_CULTIST, poll_time = 5 SECONDS, target_mob = mob_to_revive, pic_source = mob_to_revive) - if(LAZYLEN(candidates)) - var/mob/dead/observer/C = pick(candidates) + var/mob/chosen_one = SSpolling.poll_ghosts_for_target("Do you want to play as [span_danger(mob_to_revive.real_name)], an [span_notice("inactive blood cultist")]?", check_jobban = ROLE_CULTIST, role = ROLE_CULTIST, poll_time = 5 SECONDS, checked_target = mob_to_revive, alert_pic = mob_to_revive, role_name_text = "inactive cultist") + if(chosen_one) to_chat(mob_to_revive.mind, "Your physical form has been taken over by another soul due to your inactivity! Ahelp if you wish to regain your form.") - message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(mob_to_revive)]) to replace an AFK player.") + message_admins("[key_name_admin(chosen_one)] has taken control of ([key_name_admin(mob_to_revive)]) to replace an AFK player.") mob_to_revive.ghostize(FALSE) - mob_to_revive.key = C.key + mob_to_revive.key = chosen_one.key else fail_invoke() return diff --git a/code/modules/antagonists/heretic/heretic_knowledge.dm b/code/modules/antagonists/heretic/heretic_knowledge.dm index f2cf7b00047..bb59076a6bb 100644 --- a/code/modules/antagonists/heretic/heretic_knowledge.dm +++ b/code/modules/antagonists/heretic/heretic_knowledge.dm @@ -537,23 +537,22 @@ animate(summoned, 10 SECONDS, alpha = 155) message_admins("A [summoned.name] is being summoned by [ADMIN_LOOKUPFLW(user)] in [ADMIN_COORDJMP(summoned)].") - var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates_for_mob("Do you want to play as a [summoned.name]?", check_jobban = ROLE_HERETIC, poll_time = 10 SECONDS, target_mob = summoned, ignore_category = poll_ignore_define, pic_source = summoned, role_name_text = summoned.name) - if(!LAZYLEN(candidates)) + var/mob/chosen_one = SSpolling.poll_ghosts_for_target(check_jobban = ROLE_HERETIC, poll_time = 10 SECONDS, checked_target = summoned, ignore_category = poll_ignore_define, alert_pic = summoned, role_name_text = summoned.name) + if(isnull(chosen_one)) loc.balloon_alert(user, "ritual failed, no ghosts!") animate(summoned, 0.5 SECONDS, alpha = 0) QDEL_IN(summoned, 0.6 SECONDS) return FALSE - var/mob/dead/observer/picked_candidate = pick(candidates) // Ok let's make them an interactable mob now, since we got a ghost summoned.alpha = 255 REMOVE_TRAIT(summoned, TRAIT_NO_TRANSFORM, REF(src)) summoned.move_resist = initial(summoned.move_resist) summoned.ghostize(FALSE) - summoned.key = picked_candidate.key + summoned.key = chosen_one.key - user.log_message("created a [summoned.name], controlled by [key_name(picked_candidate)].", LOG_GAME) + user.log_message("created a [summoned.name], controlled by [key_name(chosen_one)].", LOG_GAME) message_admins("[ADMIN_LOOKUPFLW(user)] created a [summoned.name], [ADMIN_LOOKUPFLW(summoned)].") var/datum/antagonist/heretic_monster/heretic_monster = summoned.mind.add_antag_datum(/datum/antagonist/heretic_monster) diff --git a/code/modules/antagonists/heretic/knowledge/flesh_lore.dm b/code/modules/antagonists/heretic/knowledge/flesh_lore.dm index e69e6fbfbfc..0745dcfc803 100644 --- a/code/modules/antagonists/heretic/knowledge/flesh_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/flesh_lore.dm @@ -168,15 +168,13 @@ if(!soon_to_be_ghoul.mind || !soon_to_be_ghoul.client) message_admins("[ADMIN_LOOKUPFLW(user)] is creating a voiceless dead of a body with no player.") - var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates_for_mob("Do you want to play as a [soon_to_be_ghoul.real_name], a voiceless dead?", check_jobban = ROLE_HERETIC, role = ROLE_HERETIC, poll_time = 5 SECONDS, target_mob = soon_to_be_ghoul, pic_source = soon_to_be_ghoul, role_name_text = "voiceless dead") - if(!LAZYLEN(candidates)) + var/mob/chosen_one = SSpolling.poll_ghosts_for_target("Do you want to play as [span_danger(soon_to_be_ghoul.real_name)], a [span_notice("voiceless dead")]?", check_jobban = ROLE_HERETIC, role = ROLE_HERETIC, poll_time = 5 SECONDS, checked_target = soon_to_be_ghoul, alert_pic = mutable_appearance('icons/mob/human/human.dmi', "husk"), jump_target = soon_to_be_ghoul, role_name_text = "voiceless dead") + if(isnull(chosen_one)) loc.balloon_alert(user, "ritual failed, no ghosts!") return FALSE - - var/mob/dead/observer/chosen_candidate = pick(candidates) - message_admins("[key_name_admin(chosen_candidate)] has taken control of ([key_name_admin(soon_to_be_ghoul)]) to replace an AFK player.") + message_admins("[key_name_admin(chosen_one)] has taken control of ([key_name_admin(soon_to_be_ghoul)]) to replace an AFK player.") soon_to_be_ghoul.ghostize(FALSE) - soon_to_be_ghoul.key = chosen_candidate.key + soon_to_be_ghoul.key = chosen_one.key selected_atoms -= soon_to_be_ghoul make_ghoul(user, soon_to_be_ghoul) diff --git a/code/modules/antagonists/heretic/structures/lock_final.dm b/code/modules/antagonists/heretic/structures/lock_final.dm index 8cb6c06f3cb..759bc8aa55e 100644 --- a/code/modules/antagonists/heretic/structures/lock_final.dm +++ b/code/modules/antagonists/heretic/structures/lock_final.dm @@ -37,7 +37,7 @@ /// Ask ghosts if they want to make some noise /obj/structure/lock_tear/proc/poll_ghosts() - var/list/candidates = SSpolling.poll_ghost_candidates("Would you like to be a random eldritch monster attacking the crew?", check_jobban = ROLE_SENTIENCE, role = ROLE_SENTIENCE, poll_time = 10 SECONDS, ignore_category = POLL_IGNORE_HERETIC_MONSTER, pic_source = src, role_name_text = "eldritch monster") + var/list/candidates = SSpolling.poll_ghost_candidates("Would you like to be a random [span_notice("eldritch monster")] attacking the crew?", check_jobban = ROLE_SENTIENCE, role = ROLE_SENTIENCE, poll_time = 10 SECONDS, ignore_category = POLL_IGNORE_HERETIC_MONSTER, alert_pic = src, role_name_text = "eldritch monster") while(LAZYLEN(candidates)) var/mob/dead/observer/candidate = pick_n_take(candidates) ghost_to_monster(candidate, should_ask = FALSE) diff --git a/code/modules/antagonists/nukeop/datums/operative_team.dm b/code/modules/antagonists/nukeop/datums/operative_team.dm index e42d65b42a8..9bec3b0fcf0 100644 --- a/code/modules/antagonists/nukeop/datums/operative_team.dm +++ b/code/modules/antagonists/nukeop/datums/operative_team.dm @@ -154,19 +154,17 @@ var/tc_to_spawn = tgui_input_number(admin, "How much TC to spawn with?", "TC", 0, 100) - var/list/nuke_candidates = SSpolling.poll_ghost_candidates( - "Do you want to play as an emergency syndicate reinforcement?", + var/mob/chosen_one = SSpolling.poll_ghost_candidates( check_jobban = ROLE_OPERATIVE, role = ROLE_OPERATIVE, poll_time = 30 SECONDS, ignore_category = POLL_IGNORE_SYNDICATE, - pic_source = /obj/structure/sign/poster/contraband/gorlex_recruitment, - role_name_text = "syndicate reinforcement", + alert_pic = /obj/structure/sign/poster/contraband/gorlex_recruitment, + role_name_text = "emergency syndicate reinforcement", + amount_to_pick = 1, ) - nuke_candidates -= admin // may be easy to fat-finger say yes. so just don't - - if(!length(nuke_candidates)) + if(isnull(chosen_one)) tgui_alert(admin, "No candidates found.", "Recruitment Shortage", list("OK")) return @@ -194,10 +192,9 @@ if(infil_or_nukebase == SPAWN_AT_BASE) spawn_loc = pick(GLOB.nukeop_start) - var/mob/dead/observer/picked = pick(nuke_candidates) var/mob/living/carbon/human/nukie = new(spawn_loc) - picked.client.prefs.safe_transfer_prefs_to(nukie, is_antag = TRUE) - nukie.key = picked.key + chosen_one.client.prefs.safe_transfer_prefs_to(nukie, is_antag = TRUE) + nukie.key = chosen_one.key var/datum/antagonist/nukeop/antag_datum = new() antag_datum.send_to_spawnpoint = FALSE diff --git a/code/modules/antagonists/pirate/pirate_event.dm b/code/modules/antagonists/pirate/pirate_event.dm index f3c6655a275..e4a14182d0e 100644 --- a/code/modules/antagonists/pirate/pirate_event.dm +++ b/code/modules/antagonists/pirate/pirate_event.dm @@ -66,7 +66,7 @@ if(chosen_gang.paid_off) return - var/list/candidates = SSpolling.poll_ghost_candidates("Do you wish to be considered for a pirate crew of [chosen_gang.name]?", check_jobban = ROLE_TRAITOR, pic_source = /obj/item/claymore/cutlass, role_name_text = "pirate crew") + var/list/candidates = SSpolling.poll_ghost_candidates("Do you wish to be considered for a [span_notice("pirate crew of [chosen_gang.name]?")]", check_jobban = ROLE_TRAITOR, alert_pic = /obj/item/claymore/cutlass, role_name_text = "pirate crew") shuffle_inplace(candidates) var/template_key = "pirate_[chosen_gang.ship_template_id]" diff --git a/code/modules/antagonists/wizard/equipment/soulstone.dm b/code/modules/antagonists/wizard/equipment/soulstone.dm index 5d4c6c9deee..e46dc0c8338 100644 --- a/code/modules/antagonists/wizard/equipment/soulstone.dm +++ b/code/modules/antagonists/wizard/equipment/soulstone.dm @@ -317,15 +317,17 @@ return TRUE to_chat(user, "[span_userdanger("Capture failed!")]: The soul has already fled its mortal frame. You attempt to bring it back...") - - var/datum/callback/to_call = CALLBACK(src, PROC_REF(on_poll_concluded), user, victim) - AddComponent(/datum/component/orbit_poll, \ - ignore_key = POLL_IGNORE_SHADE, \ - job_bans = ROLE_CULTIST, \ - to_call = to_call, \ - title = "A shade" \ + var/mob/chosen_one = SSpolling.poll_ghosts_for_target( + check_jobban = ROLE_CULTIST, + poll_time = 20 SECONDS, + checked_target = src, + ignore_category = POLL_IGNORE_SHADE, + alert_pic = /mob/living/basic/shade, + jump_target = src, + role_name_text = "a shade", + chat_text_border_icon = /mob/living/basic/shade, ) - + on_poll_concluded(user, victim, chosen_one) return TRUE //it'll probably get someone ;) ///captures a shade that was previously released from a soulstone. diff --git a/code/modules/bitrunning/server/threats.dm b/code/modules/bitrunning/server/threats.dm index 3ed4ad45bc6..6c42322d0cf 100644 --- a/code/modules/bitrunning/server/threats.dm +++ b/code/modules/bitrunning/server/threats.dm @@ -69,16 +69,15 @@ var/datum/antagonist/bitrunning_glitch/chosen_role = forced_role || get_antagonist_role() var/role_name = initial(chosen_role.name) - - var/datum/callback/to_call = CALLBACK(src, PROC_REF(spawn_glitch), chosen_role, mutation_target) - mutation_target.AddComponent(/datum/component/orbit_poll, \ - ignore_key = POLL_IGNORE_GLITCH, \ - job_bans = ROLE_GLITCH, \ - to_call = to_call, \ - title = role_name, \ - header = "Bitrunning Malfunction", \ + var/mob/chosen_one = SSpolling.poll_ghosts_for_target( + check_jobban = ROLE_GLITCH, + poll_time = 20 SECONDS, + checked_target = mutation_target, + ignore_category = POLL_IGNORE_GLITCH, + alert_pic = mutation_target, + role_name_text = "Bitrunning Malfunction: [role_name]", ) - + spawn_glitch(chosen_role, mutation_target, chosen_one) return mutation_target /// Orbit poll has concluded - spawn the antag diff --git a/code/modules/clothing/head/mind_monkey_helmet.dm b/code/modules/clothing/head/mind_monkey_helmet.dm index fbe8cfe48a3..9bc4cfb7a06 100644 --- a/code/modules/clothing/head/mind_monkey_helmet.dm +++ b/code/modules/clothing/head/mind_monkey_helmet.dm @@ -47,19 +47,18 @@ playsound(src, 'sound/machines/ping.ogg', 30, TRUE) RegisterSignal(magnification, COMSIG_SPECIES_LOSS, PROC_REF(make_fall_off)) polling = TRUE - var/list/candidates = SSpolling.poll_ghost_candidates_for_mob("Do you want to play as a mind magnified monkey?", check_jobban = ROLE_MONKEY_HELMET, poll_time = 5 SECONDS, target_mob = magnification, ignore_category = POLL_IGNORE_MONKEY_HELMET, pic_source = magnification, role_name_text = "mind-magnified monkey") + var/mob/chosen_one = SSpolling.poll_ghosts_for_target(check_jobban = ROLE_MONKEY_HELMET, poll_time = 5 SECONDS, checked_target = magnification, ignore_category = POLL_IGNORE_MONKEY_HELMET, alert_pic = magnification, role_name_text = "mind-magnified monkey") polling = FALSE if(!magnification) return - if(!candidates.len) + if(isnull(chosen_one)) UnregisterSignal(magnification, COMSIG_SPECIES_LOSS) magnification = null visible_message(span_notice("[src] falls silent and drops on the floor. Maybe you should try again later?")) playsound(src, 'sound/machines/buzz-sigh.ogg', 30, TRUE) user.dropItemToGround(src) return - var/mob/picked = pick(candidates) - magnification.key = picked.key + magnification.key = chosen_one.key playsound(src, 'sound/machines/microwave/microwave-end.ogg', 100, FALSE) to_chat(magnification, span_notice("You're a mind magnified monkey! Protect your helmet with your life- if you lose it, your sentience goes with it!")) var/policy = get_policy(ROLE_MONKEY_HELMET) diff --git a/code/modules/events/ghost_role/abductor.dm b/code/modules/events/ghost_role/abductor.dm index 65fe4a142f5..dfa20885f0c 100644 --- a/code/modules/events/ghost_role/abductor.dm +++ b/code/modules/events/ghost_role/abductor.dm @@ -14,7 +14,7 @@ fakeable = FALSE //Nothing to fake here /datum/round_event/ghost_role/abductor/spawn_role() - var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates(check_jobban = ROLE_ABDUCTOR, role = ROLE_ABDUCTOR, pic_source = /obj/item/melee/baton/abductor, role_name_text = role_name) + var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates(check_jobban = ROLE_ABDUCTOR, role = ROLE_ABDUCTOR, alert_pic = /obj/item/melee/baton/abductor, role_name_text = role_name, amount_to_pick = 2) if(candidates.len < 2) return NOT_ENOUGH_PLAYERS diff --git a/code/modules/events/ghost_role/alien_infestation.dm b/code/modules/events/ghost_role/alien_infestation.dm index f4078e52e65..88e79fd7d60 100644 --- a/code/modules/events/ghost_role/alien_infestation.dm +++ b/code/modules/events/ghost_role/alien_infestation.dm @@ -62,7 +62,7 @@ message_admins("An event attempted to spawn an alien but no suitable vents were found. Shutting down.") return MAP_ERROR - var/list/candidates = SSpolling.poll_ghost_candidates(check_jobban = ROLE_ALIEN, role = ROLE_ALIEN, pic_source = /mob/living/carbon/alien/larva, role_name_text = role_name) + var/list/candidates = SSpolling.poll_ghost_candidates(check_jobban = ROLE_ALIEN, role = ROLE_ALIEN, alert_pic = /mob/living/carbon/alien/larva, role_name_text = role_name) if(!candidates.len) return NOT_ENOUGH_PLAYERS diff --git a/code/modules/events/ghost_role/blob.dm b/code/modules/events/ghost_role/blob.dm index 70640512699..8e83351f5c0 100644 --- a/code/modules/events/ghost_role/blob.dm +++ b/code/modules/events/ghost_role/blob.dm @@ -33,10 +33,10 @@ blob_icon.Blend("#9ACD32", ICON_MULTIPLY) blob_icon.Blend(icon('icons/mob/nonhuman-player/blob.dmi', "blob_core_overlay"), ICON_OVERLAY) var/image/blob_image = image(blob_icon) - var/list/candidates = SSpolling.poll_ghost_candidates(check_jobban = ROLE_BLOB, role = ROLE_BLOB, pic_source = blob_image, role_name_text = role_name) - if(!candidates.len) + var/mob/chosen_one = SSpolling.poll_ghost_candidates(check_jobban = ROLE_BLOB, role = ROLE_BLOB, alert_pic = blob_image, role_name_text = role_name, amount_to_pick = 1, chat_text_border_icon = blob_image) + if(isnull(chosen_one)) return NOT_ENOUGH_PLAYERS - var/mob/dead/observer/new_blob = pick(candidates) + var/mob/dead/observer/new_blob = chosen_one var/mob/camera/blob/BC = new_blob.become_overmind() spawned_mobs += BC message_admins("[ADMIN_LOOKUPFLW(BC)] has been made into a blob overmind by an event.") diff --git a/code/modules/events/ghost_role/changeling_event.dm b/code/modules/events/ghost_role/changeling_event.dm index 43b4ca48af5..ce34aaa07fa 100644 --- a/code/modules/events/ghost_role/changeling_event.dm +++ b/code/modules/events/ghost_role/changeling_event.dm @@ -21,12 +21,9 @@ fakeable = FALSE /datum/round_event/ghost_role/changeling/spawn_role() - var/list/mob/dead/observer/candidate = SSpolling.poll_ghost_candidates(check_jobban = ROLE_CHANGELING, role = ROLE_CHANGELING_MIDROUND, pic_source = /obj/item/melee/arm_blade, role_name_text = role_name) - - if(!candidate.len) + var/mob/chosen_one = SSpolling.poll_ghost_candidates(check_jobban = ROLE_CHANGELING, role = ROLE_CHANGELING_MIDROUND, alert_pic = /obj/item/melee/arm_blade, role_name_text = role_name, amount_to_pick = 1) + if(isnull(chosen_one)) return NOT_ENOUGH_PLAYERS - - spawned_mobs += generate_changeling_meteor(pick_n_take(candidate)) - + spawned_mobs += generate_changeling_meteor(chosen_one) if(spawned_mobs) return SUCCESSFUL_SPAWN diff --git a/code/modules/events/ghost_role/fugitive_event.dm b/code/modules/events/ghost_role/fugitive_event.dm index 4b86e751c0b..a09838ce473 100644 --- a/code/modules/events/ghost_role/fugitive_event.dm +++ b/code/modules/events/ghost_role/fugitive_event.dm @@ -20,7 +20,7 @@ if(isnull(landing_turf)) return MAP_ERROR var/list/possible_backstories = list() - var/list/candidates = SSpolling.poll_ghost_candidates(check_jobban = ROLE_FUGITIVE, role = ROLE_FUGITIVE, pic_source = /obj/item/card/id/advanced/prisoner) + var/list/candidates = SSpolling.poll_ghost_candidates(check_jobban = ROLE_FUGITIVE, role = ROLE_FUGITIVE, alert_pic = /obj/item/card/id/advanced/prisoner, jump_target = landing_turf) if(!length(candidates)) return NOT_ENOUGH_PLAYERS @@ -111,7 +111,7 @@ addtimer(CALLBACK(src, PROC_REF(check_spawn_hunters), backstory, remaining_time - 1 MINUTES), 1 MINUTES) /datum/round_event/ghost_role/fugitives/proc/spawn_hunters(backstory) - var/list/candidates = SSpolling.poll_ghost_candidates("Do you wish to be considered for a group of [backstory]?", check_jobban = ROLE_FUGITIVE_HUNTER, pic_source = /obj/machinery/sleeper, role_name_text = backstory) + var/list/candidates = SSpolling.poll_ghost_candidates("Do you wish to be considered for a group of [span_notice(backstory)]?", check_jobban = ROLE_FUGITIVE_HUNTER, alert_pic = /obj/machinery/sleeper, role_name_text = backstory) shuffle_inplace(candidates) var/datum/map_template/shuttle/hunter/ship diff --git a/code/modules/events/ghost_role/morph_event.dm b/code/modules/events/ghost_role/morph_event.dm index c9133863f8c..21d4b07873d 100644 --- a/code/modules/events/ghost_role/morph_event.dm +++ b/code/modules/events/ghost_role/morph_event.dm @@ -13,13 +13,10 @@ role_name = "morphling" /datum/round_event/ghost_role/morph/spawn_role() - var/list/candidates = SSpolling.poll_ghost_candidates(check_jobban = ROLE_ALIEN, role = ROLE_ALIEN, pic_source = /mob/living/basic/morph, role_name_text = "morph") - if(!candidates.len) + var/mob/chosen_one = SSpolling.poll_ghost_candidates(check_jobban = ROLE_ALIEN, role = ROLE_ALIEN, alert_pic = /mob/living/basic/morph, role_name_text = "morph", amount_to_pick = 1) + if(isnull(chosen_one)) return NOT_ENOUGH_PLAYERS - - var/mob/dead/selected = pick_n_take(candidates) - - var/datum/mind/player_mind = new /datum/mind(selected.key) + var/datum/mind/player_mind = new /datum/mind(chosen_one.key) player_mind.active = TRUE var/turf/spawn_loc = find_maintenance_spawn(atmos_sensitive = TRUE, require_darkness = FALSE) diff --git a/code/modules/events/ghost_role/nightmare.dm b/code/modules/events/ghost_role/nightmare.dm index ffb206c476d..d30108d94b9 100644 --- a/code/modules/events/ghost_role/nightmare.dm +++ b/code/modules/events/ghost_role/nightmare.dm @@ -15,13 +15,10 @@ fakeable = FALSE /datum/round_event/ghost_role/nightmare/spawn_role() - var/list/candidates = SSpolling.poll_ghost_candidates(check_jobban = ROLE_ALIEN, role = ROLE_NIGHTMARE, role_name_text = role_name) - if(!candidates.len) + var/mob/chosen_one = SSpolling.poll_ghost_candidates(check_jobban = ROLE_ALIEN, role = ROLE_NIGHTMARE, role_name_text = role_name, amount_to_pick = 1) + if(isnull(chosen_one)) return NOT_ENOUGH_PLAYERS - - var/mob/dead/selected = pick(candidates) - - var/datum/mind/player_mind = new /datum/mind(selected.key) + var/datum/mind/player_mind = new /datum/mind(chosen_one.key) player_mind.active = TRUE var/turf/spawn_loc = find_maintenance_spawn(atmos_sensitive = TRUE, require_darkness = TRUE) diff --git a/code/modules/events/ghost_role/operative.dm b/code/modules/events/ghost_role/operative.dm index fcea52e3c02..98cfe5ecad4 100644 --- a/code/modules/events/ghost_role/operative.dm +++ b/code/modules/events/ghost_role/operative.dm @@ -12,20 +12,16 @@ fakeable = FALSE /datum/round_event/ghost_role/operative/spawn_role() - var/list/candidates = SSpolling.poll_ghost_candidates(check_jobban = ROLE_OPERATIVE, role = ROLE_LONE_OPERATIVE, pic_source = /obj/machinery/nuclearbomb) - if(!candidates.len) + var/mob/chosen_one = SSpolling.poll_ghost_candidates(check_jobban = ROLE_OPERATIVE, role = ROLE_LONE_OPERATIVE, alert_pic = /obj/machinery/nuclearbomb, amount_to_pick = 1) + if(isnull(chosen_one)) return NOT_ENOUGH_PLAYERS - - var/mob/dead/selected = pick_n_take(candidates) - var/spawn_location = find_space_spawn() if(isnull(spawn_location)) return MAP_ERROR - var/mob/living/carbon/human/operative = new(spawn_location) operative.randomize_human_appearance(~RANDOMIZE_SPECIES) operative.dna.update_dna_identity() - var/datum/mind/Mind = new /datum/mind(selected.key) + var/datum/mind/Mind = new /datum/mind(chosen_one.key) Mind.set_assigned_role(SSjob.GetJobType(/datum/job/lone_operative)) Mind.special_role = ROLE_LONE_OPERATIVE Mind.active = TRUE diff --git a/code/modules/events/ghost_role/revenant_event.dm b/code/modules/events/ghost_role/revenant_event.dm index 6cdfc2c4c9e..7af53b847c8 100644 --- a/code/modules/events/ghost_role/revenant_event.dm +++ b/code/modules/events/ghost_role/revenant_event.dm @@ -30,14 +30,10 @@ message_admins("Event attempted to spawn a revenant, but there were only [deadMobs]/[REVENANT_SPAWN_THRESHOLD] dead mobs.") return WAITING_FOR_SOMETHING - var/list/candidates = SSpolling.poll_ghost_candidates(check_jobban = ROLE_REVENANT, role = ROLE_REVENANT, pic_source = /mob/living/basic/revenant) - if(!candidates.len) + var/mob/chosen_one = SSpolling.poll_ghost_candidates(check_jobban = ROLE_REVENANT, role = ROLE_REVENANT, alert_pic = /mob/living/basic/revenant, amount_to_pick = 1) + if(isnull(chosen_one)) return NOT_ENOUGH_PLAYERS - - var/mob/dead/observer/selected = pick_n_take(candidates) - var/list/spawn_locs = list() - for(var/mob/living/L in GLOB.dead_mob_list) //look for any dead bodies var/turf/T = get_turf(L) if(T && is_station_level(T.z)) @@ -50,16 +46,16 @@ if(!spawn_locs.len) //If we can't find any valid spawnpoints, try the carp spawns spawn_locs += find_space_spawn() if(!spawn_locs.len) //If we can't find either, just spawn the revenant at the player's location - spawn_locs += get_turf(selected) + spawn_locs += get_turf(chosen_one) if(!spawn_locs.len) //If we can't find THAT, then just give up and cry return MAP_ERROR var/mob/living/basic/revenant/revvie = new(pick(spawn_locs)) - revvie.key = selected.key + revvie.key = chosen_one.key message_admins("[ADMIN_LOOKUPFLW(revvie)] has been made into a revenant by an event.") revvie.log_message("was spawned as a revenant by an event.", LOG_GAME) spawned_mobs += revvie - qdel(selected) + qdel(chosen_one) return SUCCESSFUL_SPAWN #undef REVENANT_SPAWN_THRESHOLD diff --git a/code/modules/events/ghost_role/sentience.dm b/code/modules/events/ghost_role/sentience.dm index 8ebd30ad7b3..3aeebd298f4 100644 --- a/code/modules/events/ghost_role/sentience.dm +++ b/code/modules/events/ghost_role/sentience.dm @@ -50,7 +50,7 @@ GLOBAL_LIST_INIT(high_priority_sentience, typecacheof(list( /datum/round_event/ghost_role/sentience/spawn_role() var/list/mob/dead/observer/candidates - candidates = SSpolling.poll_ghost_candidates(check_jobban = ROLE_SENTIENCE, role = ROLE_SENTIENCE, pic_source = /obj/item/slimepotion/slime/sentience, role_name_text = role_name) + candidates = SSpolling.poll_ghost_candidates(check_jobban = ROLE_SENTIENCE, role = ROLE_SENTIENCE, alert_pic = /obj/item/slimepotion/slime/sentience, role_name_text = role_name) // find our chosen mob to breathe life into // Mobs have to be simple animals, mindless, on station, and NOT holograms. diff --git a/code/modules/events/ghost_role/sentient_disease.dm b/code/modules/events/ghost_role/sentient_disease.dm index 44f78d7c08c..156988d4b20 100644 --- a/code/modules/events/ghost_role/sentient_disease.dm +++ b/code/modules/events/ghost_role/sentient_disease.dm @@ -13,14 +13,11 @@ role_name = "sentient disease" /datum/round_event/ghost_role/sentient_disease/spawn_role() - var/list/candidates = SSpolling.poll_ghost_candidates(check_jobban = ROLE_ALIEN, role = ROLE_ALIEN, pic_source = /obj/structure/sign/warning/biohazard, role_name_text = role_name) - if(!candidates.len) + var/mob/chosen_one = SSpolling.poll_ghost_candidates(check_jobban = ROLE_ALIEN, role = ROLE_ALIEN, alert_pic = /obj/structure/sign/warning/biohazard, role_name_text = role_name, amount_to_pick = 1) + if(isnull(chosen_one)) return NOT_ENOUGH_PLAYERS - - var/mob/dead/observer/selected = pick_n_take(candidates) - var/mob/camera/disease/virus = new /mob/camera/disease(SSmapping.get_station_center()) - virus.key = selected.key + virus.key = chosen_one.key INVOKE_ASYNC(virus, TYPE_PROC_REF(/mob/camera/disease, pick_name)) message_admins("[ADMIN_LOOKUPFLW(virus)] has been made into a sentient disease by an event.") virus.log_message("was spawned as a sentient disease by an event.", LOG_GAME) diff --git a/code/modules/events/ghost_role/slaughter_event.dm b/code/modules/events/ghost_role/slaughter_event.dm index f4628344d2f..2ea86551b79 100644 --- a/code/modules/events/ghost_role/slaughter_event.dm +++ b/code/modules/events/ghost_role/slaughter_event.dm @@ -16,13 +16,10 @@ role_name = "slaughter demon" /datum/round_event/ghost_role/slaughter/spawn_role() - var/list/candidates = SSpolling.poll_ghost_candidates(check_jobban = ROLE_ALIEN, role = ROLE_ALIEN, pic_source = /mob/living/basic/demon/slaughter, role_name_text = role_name) - if(!candidates.len) + var/mob/chosen_one = SSpolling.poll_ghost_candidates(check_jobban = ROLE_ALIEN, role = ROLE_ALIEN, alert_pic = /mob/living/basic/demon/slaughter, role_name_text = role_name, amount_to_pick = 1) + if(isnull(chosen_one)) return NOT_ENOUGH_PLAYERS - - var/mob/dead/selected = pick_n_take(candidates) - - var/datum/mind/player_mind = new /datum/mind(selected.key) + var/datum/mind/player_mind = new /datum/mind(chosen_one.key) player_mind.active = TRUE var/spawn_location = find_space_spawn() diff --git a/code/modules/events/ghost_role/space_dragon.dm b/code/modules/events/ghost_role/space_dragon.dm index 0a328f6dc8d..8a39d4a5dae 100644 --- a/code/modules/events/ghost_role/space_dragon.dm +++ b/code/modules/events/ghost_role/space_dragon.dm @@ -19,20 +19,14 @@ priority_announce("A large organic energy flux has been recorded near [station_name()], please stand by.", "Lifesign Alert") /datum/round_event/ghost_role/space_dragon/spawn_role() - - var/list/candidates = SSpolling.poll_ghost_candidates(check_jobban = ROLE_SPACE_DRAGON, role = ROLE_SPACE_DRAGON, pic_source = /mob/living/basic/space_dragon) - if(!candidates.len) + var/mob/chosen_one = SSpolling.poll_ghost_candidates(check_jobban = ROLE_SPACE_DRAGON, role = ROLE_SPACE_DRAGON, alert_pic = /mob/living/basic/space_dragon, amount_to_pick = 1) + if(isnull(chosen_one)) return NOT_ENOUGH_PLAYERS - - var/mob/dead/selected = pick(candidates) - var/key = selected.key - var/spawn_location = find_space_spawn() if(isnull(spawn_location)) return MAP_ERROR - - var/mob/living/basic/space_dragon/dragon = new (spawn_location) - dragon.key = key + var/mob/living/basic/space_dragon/dragon = new(spawn_location) + dragon.key = chosen_one.key dragon.mind.add_antag_datum(/datum/antagonist/space_dragon) playsound(dragon, 'sound/magic/ethereal_exit.ogg', 50, TRUE, -1) message_admins("[ADMIN_LOOKUPFLW(dragon)] has been made into a Space Dragon by an event.") diff --git a/code/modules/events/ghost_role/space_ninja.dm b/code/modules/events/ghost_role/space_ninja.dm index d7da1e4a53e..cde5a3ae48e 100644 --- a/code/modules/events/ghost_role/space_ninja.dm +++ b/code/modules/events/ghost_role/space_ninja.dm @@ -19,16 +19,12 @@ return MAP_ERROR //selecting a candidate player - var/list/candidates = SSpolling.poll_ghost_candidates(check_jobban = ROLE_NINJA, role = ROLE_NINJA, pic_source = /obj/item/energy_katana) - if(!candidates.len) + var/mob/chosen_one = SSpolling.poll_ghost_candidates(check_jobban = ROLE_NINJA, role = ROLE_NINJA, alert_pic = /obj/item/energy_katana, jump_target = spawn_location, role_name_text = "space ninja", amount_to_pick = 1) + if(isnull(chosen_one)) return NOT_ENOUGH_PLAYERS - - var/mob/dead/selected_candidate = pick(candidates) - var/key = selected_candidate.key - //spawn the ninja and assign the candidate var/mob/living/carbon/human/ninja = create_space_ninja(spawn_location) - ninja.key = key + ninja.key = chosen_one.key ninja.mind.add_antag_datum(/datum/antagonist/ninja) spawned_mobs += ninja // NOVA EDIT ADDITION BEGIN: Preference Ninjas diff --git a/code/modules/events/holiday/vday.dm b/code/modules/events/holiday/vday.dm index 7eb89e84bc0..2d8a3bc5496 100644 --- a/code/modules/events/holiday/vday.dm +++ b/code/modules/events/holiday/vday.dm @@ -79,14 +79,15 @@ poll_time = 30 SECONDS, flash_window = FALSE, start_signed_up = TRUE, - pic_source = /obj/item/storage/fancy/heart_box, + alert_pic = /obj/item/storage/fancy/heart_box, custom_response_messages = list( POLL_RESPONSE_SIGNUP = "You have signed up for a date!", POLL_RESPONSE_ALREADY_SIGNED = "You are already signed up for a date.", POLL_RESPONSE_NOT_SIGNED = "You aren't signed up for a date.", POLL_RESPONSE_TOO_LATE_TO_UNREGISTER = "It's too late to decide against going on a date.", - POLL_RESPONSE_UNREGISTERED = "You deicde against going on a date.", + POLL_RESPONSE_UNREGISTERED = "You decide against going on a date.", ), + chat_text_border_icon = /obj/item/storage/fancy/heart_box, ) for(var/mob/living/second_check as anything in candidates_pruned) diff --git a/code/modules/events/holiday/xmas.dm b/code/modules/events/holiday/xmas.dm index cad343f7deb..20c4af94abd 100644 --- a/code/modules/events/holiday/xmas.dm +++ b/code/modules/events/holiday/xmas.dm @@ -84,11 +84,9 @@ priority_announce("Santa is coming to town!", "Unknown Transmission") /datum/round_event/santa/start() - var/list/candidates = SSpolling.poll_ghost_candidates("Santa is coming to town! Do you want to be Santa?", poll_time = 15 SECONDS, pic_source = /obj/item/clothing/head/costume/santa, role_name_text = "santa") - if(LAZYLEN(candidates)) - var/mob/dead/observer/C = pick(candidates) + var/mob/chosen_one = SSpolling.poll_ghost_candidates("Santa is coming to town! Do you want to be [span_notice("Santa")]?", poll_time = 15 SECONDS, alert_pic = /obj/item/clothing/head/costume/santa, role_name_text = "santa", amount_to_pick = 1) + if(chosen_one) santa = new /mob/living/carbon/human(pick(GLOB.blobstart)) - santa.key = C.key - + santa.key = chosen_one.key var/datum/antagonist/santa/A = new santa.mind.add_antag_datum(A) diff --git a/code/modules/events/wizard/imposter.dm b/code/modules/events/wizard/imposter.dm index 82994226142..c2fb5472bdd 100644 --- a/code/modules/events/wizard/imposter.dm +++ b/code/modules/events/wizard/imposter.dm @@ -13,20 +13,17 @@ if(!ishuman(M.current)) continue var/mob/living/carbon/human/W = M.current - var/list/candidates = SSpolling.poll_ghost_candidates("Would you like to be an imposter wizard?", check_jobban = ROLE_WIZARD, pic_source = /obj/item/clothing/head/wizard, role_name_text = "imposter wizard") - if(!length(candidates)) + var/mob/chosen_one = SSpolling.poll_ghost_candidates("Would you like to be an [span_notice("imposter wizard")]?", check_jobban = ROLE_WIZARD, alert_pic = /obj/item/clothing/head/wizard, jump_target = W, role_name_text = "imposter wizard", amount_to_pick = 1) + if(isnull(chosen_one)) return //Sad Trombone - var/mob/dead/observer/C = pick(candidates) - new /obj/effect/particle_effect/fluid/smoke(W.loc) - var/mob/living/carbon/human/I = new /mob/living/carbon/human(W.loc) W.dna.transfer_identity(I, transfer_SE=1) I.real_name = I.dna.real_name I.name = I.dna.real_name I.updateappearance(mutcolor_update=1) I.domutcheck() - I.key = C.key + I.key = chosen_one.key var/datum/antagonist/wizard/master = M.has_antag_datum(/datum/antagonist/wizard) if(!master.wiz_team) master.create_wiz_team() diff --git a/code/modules/mining/lavaland/megafauna_loot.dm b/code/modules/mining/lavaland/megafauna_loot.dm index 0c9822b43c9..d9beb9b2446 100644 --- a/code/modules/mining/lavaland/megafauna_loot.dm +++ b/code/modules/mining/lavaland/megafauna_loot.dm @@ -424,13 +424,16 @@ using = TRUE balloon_alert(user, "you hold the scythe up...") ADD_TRAIT(src, TRAIT_NODROP, type) - - var/datum/callback/to_call = CALLBACK(src, PROC_REF(on_poll_concluded), user) - AddComponent(/datum/component/orbit_poll, \ - ignore_key = POLL_IGNORE_POSSESSED_BLADE, \ - job_bans = ROLE_PAI, \ - to_call = to_call, \ + var/mob/chosen_one = SSpolling.poll_ghosts_for_target( + check_jobban = ROLE_PAI, + poll_time = 20 SECONDS, + checked_target = src, + ignore_category = POLL_IGNORE_POSSESSED_BLADE, + alert_pic = src, + role_name_text = "soulscythe soul", + chat_text_border_icon = src, ) + on_poll_concluded(user, chosen_one) /// Ghost poll has concluded and a candidate has been chosen. /obj/item/soulscythe/proc/on_poll_concluded(mob/living/master, mob/dead/observer/ghost) diff --git a/code/modules/mob/living/basic/guardian/guardian_creator.dm b/code/modules/mob/living/basic/guardian/guardian_creator.dm index 3f1f0927522..441a60124a7 100644 --- a/code/modules/mob/living/basic/guardian/guardian_creator.dm +++ b/code/modules/mob/living/basic/guardian/guardian_creator.dm @@ -87,17 +87,18 @@ GLOBAL_LIST_INIT(guardian_radial_images, setup_guardian_radial()) used = TRUE to_chat(user, use_message) var/guardian_type_name = random ? "Random" : capitalize(initial(guardian_path.creator_name)) - var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates( - "Do you want to play as [user.real_name]'s [guardian_type_name] [mob_name]?", + var/mob/chosen_one = SSpolling.poll_ghost_candidates( + "Do you want to play as [span_danger("[user.real_name]'s")] [span_notice("[guardian_type_name] [mob_name]")]?", check_jobban = ROLE_PAI, poll_time = 10 SECONDS, ignore_category = POLL_IGNORE_HOLOPARASITE, - pic_source = src, - role_name_text = "guardian spirit", + alert_pic = guardian_path, + jump_target = src, + role_name_text = guardian_type_name, + amount_to_pick = 1, ) - if(LAZYLEN(candidates)) - var/mob/dead/observer/candidate = pick(candidates) - spawn_guardian(user, candidate, guardian_path) + if(chosen_one) + spawn_guardian(user, chosen_one, guardian_path) used = TRUE SEND_SIGNAL(src, COMSIG_TRAITOR_ITEM_USED(type)) else diff --git a/code/modules/mob/living/basic/guardian/guardian_verbs.dm b/code/modules/mob/living/basic/guardian/guardian_verbs.dm index 2f40da369f8..80a2af7db7a 100644 --- a/code/modules/mob/living/basic/guardian/guardian_verbs.dm +++ b/code/modules/mob/living/basic/guardian/guardian_verbs.dm @@ -169,20 +169,18 @@ return FALSE to_chat(owner, span_holoparasite("You attempt to reset [span_bold(chosen_guardian.real_name)]'s personality...")) - var/list/mob/dead/observer/ghost_candidates = SSpolling.poll_ghost_candidates("Do you want to play as [owner.real_name]'s [chosen_guardian.theme.name]?", check_jobban = ROLE_PAI, poll_time = 10 SECONDS, pic_source = chosen_guardian, role_name_text = chosen_guardian.theme.name) - if (!LAZYLEN(ghost_candidates)) + var/mob/chosen_one = SSpolling.poll_ghost_candidates("Do you want to play as [span_danger("[owner.real_name]'s")] [span_notice(chosen_guardian.theme.name)]?", check_jobban = ROLE_PAI, poll_time = 10 SECONDS, alert_pic = chosen_guardian, jump_target = owner, role_name_text = chosen_guardian.theme.name, amount_to_pick = 1) + if(isnull(chosen_one)) to_chat(owner, span_holoparasite("Your attempt to reset the personality of \ [span_bold(chosen_guardian.real_name)] appears to have failed... \ Looks like you're stuck with it for now.")) StartCooldown() return FALSE - - var/mob/dead/observer/candidate = pick(ghost_candidates) to_chat(chosen_guardian, span_holoparasite("Your user reset you, and your body was taken over by a ghost. Looks like they weren't happy with your performance.")) to_chat(owner, span_boldholoparasite("The personality of [chosen_guardian.theme.name] has been successfully reset.")) - message_admins("[key_name_admin(candidate)] has taken control of ([ADMIN_LOOKUPFLW(chosen_guardian)])") + message_admins("[key_name_admin(chosen_one)] has taken control of ([ADMIN_LOOKUPFLW(chosen_guardian)])") chosen_guardian.ghostize(FALSE) - chosen_guardian.key = candidate.key + chosen_guardian.key = chosen_one.key COOLDOWN_START(chosen_guardian, resetting_cooldown, 5 MINUTES) chosen_guardian.guardian_rename() //give it a new color and name, to show it's a new person chosen_guardian.guardian_recolour() diff --git a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm index be83d3e058f..51379ce88a0 100644 --- a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm +++ b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm @@ -62,6 +62,7 @@ poll_ignore_key = POLL_IGNORE_REGAL_RAT,\ assumed_control_message = "You are an independent, invasive force on the station! Hoard coins, trash, cheese, and the like from the safety of darkness!",\ after_assumed_control = CALLBACK(src, PROC_REF(became_player_controlled)),\ + poll_chat_border_icon = /obj/item/food/cheese/wedge,\ ) var/static/list/innate_actions = list( diff --git a/code/modules/mob/living/basic/space_fauna/revenant/revenant_items.dm b/code/modules/mob/living/basic/space_fauna/revenant/revenant_items.dm index ea153b03c06..f8a3db0202a 100644 --- a/code/modules/mob/living/basic/space_fauna/revenant/revenant_items.dm +++ b/code/modules/mob/living/basic/space_fauna/revenant/revenant_items.dm @@ -86,21 +86,11 @@ /// Handles giving the revenant a new client to control it /obj/item/ectoplasm/revenant/proc/get_new_user() message_admins("The new revenant's old client either could not be found or is in a new, living mob - grabbing a random candidate instead...") - var/list/candidates = SSpolling.poll_ghost_candidates_for_mob("Do you want to be [revenant.name] (reforming)?", check_jobban = ROLE_REVENANT, role = ROLE_REVENANT, poll_time = 5 SECONDS, target_mob = revenant, pic_source = revenant) - - if(!LAZYLEN(candidates)) + var/mob/chosen_one = SSpolling.poll_ghosts_for_target("Do you want to be [span_notice(revenant.name)] (reforming)?", check_jobban = ROLE_REVENANT, role = ROLE_REVENANT, poll_time = 5 SECONDS, checked_target = revenant, alert_pic = revenant, role_name_text = "reforming revenant", chat_text_border_icon = revenant) + if(isnull(chosen_one)) message_admins("No candidates were found for the new revenant.") inert = TRUE visible_message(span_revenwarning("[src] settles down and seems lifeless.")) qdel(revenant) return null - - var/mob/dead/observer/potential_client = pick(candidates) - if(isnull(potential_client)) - qdel(revenant) - message_admins("No candidate was found for the new revenant. Oh well!") - inert = TRUE - visible_message(span_revenwarning("[src] settles down and seems lifeless.")) - return null - - return potential_client + return chosen_one diff --git a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm index 3a72dc61dc6..b1937d210d2 100644 --- a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm +++ b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm @@ -90,15 +90,18 @@ return bursting = TRUE - - var/datum/callback/to_call = CALLBACK(src, PROC_REF(on_poll_concluded), gib_on_success) - owner.AddComponent(/datum/component/orbit_poll, \ - ignore_key = POLL_IGNORE_ALIEN_LARVA, \ - job_bans = ROLE_ALIEN, \ - to_call = to_call, \ - custom_message = "An alien is bursting out of [owner.real_name]", \ - title = "alien larva" \ + var/mob/chosen_one = SSpolling.poll_ghosts_for_target( + question = "An [span_notice("alien")] is bursting out of [span_danger(owner.real_name)]!", + role = ROLE_ALIEN, + check_jobban = ROLE_ALIEN, + poll_time = 20 SECONDS, + checked_target = src, + ignore_category = POLL_IGNORE_ALIEN_LARVA, + alert_pic = owner, + role_name_text = "alien larva", + chat_text_border_icon = /mob/living/carbon/alien/larva, ) + on_poll_concluded(gib_on_success, chosen_one) /// Poll has concluded with a suitor /obj/item/organ/internal/body_egg/alien_embryo/proc/on_poll_concluded(gib_on_success, mob/dead/observer/ghost) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index d0c082bfe44..0353da0369c 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -2657,10 +2657,9 @@ GLOBAL_LIST_EMPTY(fire_appearances) if(isnull(guardian_client)) return else if(guardian_client == "Poll Ghosts") - var/list/candidates = SSpolling.poll_ghost_candidates("Do you want to play as an admin created Guardian Spirit of [real_name]?", check_jobban = ROLE_PAI, poll_time = 10 SECONDS, ignore_category = POLL_IGNORE_HOLOPARASITE, pic_source = src, role_name_text = "guardian spirit") - if(LAZYLEN(candidates)) - var/mob/dead/observer/candidate = pick(candidates) - guardian_client = candidate.client + var/mob/chosen_one = SSpolling.poll_ghost_candidates("Do you want to play as an admin created [span_notice("Guardian Spirit")] of [span_danger(real_name)]?", check_jobban = ROLE_PAI, poll_time = 10 SECONDS, ignore_category = POLL_IGNORE_HOLOPARASITE, alert_pic = mutable_appearance('icons/mob/nonhuman-player/guardian.dmi', "magicexample"), jump_target = src, role_name_text = "guardian spirit", amount_to_pick = 1) + if(chosen_one) + guardian_client = chosen_one.client else tgui_alert(admin, "No ghost candidates.", "Guardian Controller") return diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm index 6386fa272b7..e33578ecc55 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm @@ -187,10 +187,10 @@ While using this makes the system rely on OnFire, it still gives options for tim addtimer(CALLBACK(src, PROC_REF(spawn_elite)), 30) return visible_message(span_boldwarning("Something within [src] stirs...")) - var/list/candidates = SSpolling.poll_ghost_candidates_for_mob("Do you want to play as a lavaland elite?", check_jobban = ROLE_SENTIENCE, role = ROLE_SENTIENCE, poll_time = 5 SECONDS, target_mob = src, ignore_category = POLL_IGNORE_LAVALAND_ELITE, pic_source = src, role_name_text = "lavaland elite") - if(candidates.len) + var/mob/chosen_one = SSpolling.poll_ghosts_for_target(check_jobban = ROLE_SENTIENCE, role = ROLE_SENTIENCE, poll_time = 5 SECONDS, checked_target = src, ignore_category = POLL_IGNORE_LAVALAND_ELITE, alert_pic = src, role_name_text = "lavaland elite") + if(chosen_one) audible_message(span_boldwarning("The stirring sounds increase in volume!")) - elitemind = pick(candidates) + elitemind = chosen_one elitemind.playsound_local(get_turf(elitemind), 'sound/effects/magic.ogg', 40, 0) to_chat(elitemind, "You have been chosen to play as a Lavaland Elite.\nIn a few seconds, you will be summoned on Lavaland as a monster to fight your activator, in a fight to the death.\n\ Your attacks can be switched using the buttons on the top left of the HUD, and used by clicking on targets or tiles similar to a gun.\n\ diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index d2b8ce0f3c3..7a8c993f26b 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -355,23 +355,22 @@ if(usr) log_admin("[key_name(usr)] has offered control of ([key_name(M)]) to ghosts.") message_admins("[key_name_admin(usr)] has offered control of ([ADMIN_LOOKUPFLW(M)]) to ghosts") - var/poll_message = "Do you want to play as [M.real_name]?" + var/poll_message = "Do you want to play as [span_danger(M.real_name)]?" if(M.mind) - poll_message = "[poll_message] Job: [M.mind.assigned_role.title]." + poll_message = "[poll_message] Job: [span_notice(M.mind.assigned_role.title)]." if(M.mind.special_role) - poll_message = "[poll_message] Status: [M.mind.special_role]." + poll_message = "[poll_message] Status: [span_boldnotice(M.mind.special_role)]." else var/datum/antagonist/A = M.mind.has_antag_datum(/datum/antagonist/) if(A) - poll_message = "[poll_message] Status: [A.name]." - var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates_for_mob(poll_message, check_jobban = ROLE_PAI, poll_time = 10 SECONDS, target_mob = M, pic_source = M, role_name_text = "ghost control") + poll_message = "[poll_message] Status: [span_boldnotice(A.name)]." + var/mob/chosen_one = SSpolling.poll_ghosts_for_target(poll_message, check_jobban = ROLE_PAI, poll_time = 10 SECONDS, checked_target = M, alert_pic = M, role_name_text = "ghost control") - if(LAZYLEN(candidates)) - var/mob/dead/observer/C = pick(candidates) + if(chosen_one) to_chat(M, "Your mob has been taken over by a ghost!") - message_admins("[key_name_admin(C)] has taken control of ([ADMIN_LOOKUPFLW(M)])") + message_admins("[key_name_admin(chosen_one)] has taken control of ([ADMIN_LOOKUPFLW(M)])") M.ghostize(FALSE) - M.key = C.key + M.key = chosen_one.key M.client?.init_verbs() return TRUE else diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index ca82e13e803..28d89cf4cb4 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -184,11 +184,10 @@ to_chat(src, "You are job banned from cyborg! Appeal your job ban if you want to avoid this in the future!") ghostize(FALSE) - var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates_for_mob("Do you want to play as [src]?", check_jobban = JOB_CYBORG, poll_time = 5 SECONDS, target_mob = src, pic_source = src, role_name_text = "cyborg") - if(LAZYLEN(candidates)) - var/mob/dead/observer/chosen_candidate = pick(candidates) - message_admins("[key_name_admin(chosen_candidate)] has taken control of ([key_name_admin(src)]) to replace a jobbanned player.") - key = chosen_candidate.key + var/mob/chosen_one = SSpolling.poll_ghosts_for_target("Do you want to play as [span_notice(src)]?", check_jobban = JOB_CYBORG, poll_time = 5 SECONDS, checked_target = src, alert_pic = src, role_name_text = "cyborg") + if(chosen_one) + message_admins("[key_name_admin(chosen_one)] has taken control of ([key_name_admin(src)]) to replace a jobbanned player.") + key = chosen_one.key //human -> alien /mob/living/carbon/human/proc/Alienize() diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index ae91fb6c603..e52d38b3da1 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -362,24 +362,23 @@ /obj/projectile/magic/wipe/proc/possession_test(mob/living/carbon/target) var/datum/brain_trauma/special/imaginary_friend/trapped_owner/trauma = target.gain_trauma(/datum/brain_trauma/special/imaginary_friend/trapped_owner) - var/poll_message = "Do you want to play as [target.real_name]?" + var/poll_message = "Do you want to play as [span_danger(target.real_name)]?" if(target.mind) - poll_message = "[poll_message] Job:[target.mind.assigned_role.title]." + poll_message = "[poll_message] Job:[span_notice(target.mind.assigned_role.title)]." if(target.mind && target.mind.special_role) - poll_message = "[poll_message] Status:[target.mind.special_role]." + poll_message = "[poll_message] Status:[span_boldnotice(target.mind.special_role)]." else if(target.mind) var/datum/antagonist/A = target.mind.has_antag_datum(/datum/antagonist/) if(A) - poll_message = "[poll_message] Status:[A.name]." - var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates_for_mob(poll_message, check_jobban = ROLE_PAI, poll_time = 10 SECONDS, target_mob = target, pic_source = target, role_name_text = "bolt of possession") + poll_message = "[poll_message] Status:[span_boldnotice(A.name)]." + var/mob/chosen_one = SSpolling.poll_ghosts_for_target(poll_message, check_jobban = ROLE_PAI, poll_time = 10 SECONDS, checked_target = target, alert_pic = target, role_name_text = "bolt of possession") if(target.stat == DEAD)//boo. return - if(LAZYLEN(candidates)) - var/mob/dead/observer/ghost = pick(candidates) + if(chosen_one) to_chat(target, span_boldnotice("You have been noticed by a ghost and it has possessed you!")) var/oldkey = target.key target.ghostize(FALSE) - target.key = ghost.key + target.key = chosen_one.key trauma.friend.key = oldkey trauma.friend.reset_perspective(null) trauma.friend.Show() diff --git a/code/modules/religion/sparring/sparring_datum.dm b/code/modules/religion/sparring/sparring_datum.dm index bfaa94d65a8..78de2bd3a0b 100644 --- a/code/modules/religion/sparring/sparring_datum.dm +++ b/code/modules/religion/sparring/sparring_datum.dm @@ -301,4 +301,4 @@ return to_chat(loser, span_userdanger("You've lost ownership over your soul to [winner]!")) var/obj/item/soulstone/anybody/chaplain/sparring/shard = new(shard_turf) - shard.capture_soul(loser, winner, forced = TRUE) + INVOKE_ASYNC(shard, TYPE_PROC_REF(/obj/item/soulstone, capture_soul), loser, winner, forced = TRUE) diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 49f7bfa61f3..ba568c4bc74 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -688,7 +688,6 @@ desc = "A miraculous chemical mix that grants human like intelligence to living beings." icon = 'icons/obj/medical/chemical.dmi' icon_state = "potpink" - var/list/not_interested = list() var/being_used = FALSE var/sentience_type = SENTIENCE_ORGANIC @@ -704,16 +703,22 @@ if(!dumb_mob.compare_sentience_type(sentience_type)) // Will also return false if not a basic or simple mob, which are the only two we want anyway balloon_alert(user, "invalid creature!") return - + var/potion_reason = tgui_input_text(user, "For what reason?", "Intelligence Potion", multiline = TRUE, timeout = 2 MINUTES) + if(isnull(potion_reason)) + return balloon_alert(user, "offering...") being_used = TRUE - - var/datum/callback/to_call = CALLBACK(src, PROC_REF(on_poll_concluded), user, dumb_mob) - dumb_mob.AddComponent(/datum/component/orbit_poll, \ - ignore_key = POLL_IGNORE_SENTIENCE_POTION, \ - job_bans = ROLE_SENTIENCE, \ - to_call = to_call, \ + var/mob/chosen_one = SSpolling.poll_ghosts_for_target( + question = "[span_danger(user)] is offering [span_notice(dumb_mob)] an intelligence potion! Reason: [span_boldnotice(potion_reason)]", + check_jobban = ROLE_SENTIENCE, + poll_time = 20 SECONDS, + checked_target = dumb_mob, + ignore_category = POLL_IGNORE_SENTIENCE_POTION, + alert_pic = dumb_mob, + role_name_text = "intelligence potion", + chat_text_border_icon = src, ) + on_poll_concluded(user, dumb_mob, chosen_one) /// Assign the chosen ghost to the mob /obj/item/slimepotion/slime/sentience/proc/on_poll_concluded(mob/user, mob/living/dumb_mob, mob/dead/observer/ghost) diff --git a/code/modules/shuttle/battlecruiser_starfury.dm b/code/modules/shuttle/battlecruiser_starfury.dm index e95ff4243f5..a27cadacad2 100644 --- a/code/modules/shuttle/battlecruiser_starfury.dm +++ b/code/modules/shuttle/battlecruiser_starfury.dm @@ -135,7 +135,7 @@ */ /proc/summon_battlecruiser(datum/team/battlecruiser/team) - var/list/candidates = SSpolling.poll_ghost_candidates("Do you wish to be considered for battlecruiser crew?", check_jobban = ROLE_TRAITOR, pic_source = /obj/machinery/sleeper/syndie, role_name_text = "battlecruiser crew") + var/list/candidates = SSpolling.poll_ghost_candidates("Do you wish to be considered for [span_notice("battlecruiser crew")]?", check_jobban = ROLE_TRAITOR, alert_pic = /obj/machinery/sleeper/syndie, role_name_text = "battlecruiser crew") shuffle_inplace(candidates) var/datum/map_template/ship = SSmapping.map_templates["battlecruiser_starfury.dmm"] diff --git a/code/modules/shuttle/shuttle_events/player_controlled.dm b/code/modules/shuttle/shuttle_events/player_controlled.dm index 77fee390a68..86d134f29f7 100644 --- a/code/modules/shuttle/shuttle_events/player_controlled.dm +++ b/code/modules/shuttle/shuttle_events/player_controlled.dm @@ -17,17 +17,12 @@ /// Attempt to grant control of a mob to ghosts before spawning it in. if spawn_anyway_if_no_player = TRUE, we spawn the mob even if there's no ghosts /datum/shuttle_event/simple_spawner/player_controlled/proc/try_grant_ghost_control(spawn_type) - var/list/candidates = SSpolling.poll_ghost_candidates(ghost_alert_string + " (Warning: you will not be able to return to your body!)", check_jobban = role_type, poll_time = 10 SECONDS, pic_source = spawn_type, role_name_text = "shot at shuttle") - - if(!candidates.len && !spawn_anyway_if_no_player) + var/mob/chosen_one = SSpolling.poll_ghost_candidates(ghost_alert_string + " (Warning: you will not be able to return to your body!)", check_jobban = role_type, poll_time = 10 SECONDS, alert_pic = spawn_type, role_name_text = "shot at shuttle", amount_to_pick = 1) + if(isnull(chosen_one) && !spawn_anyway_if_no_player) return - var/mob/living/new_mob = new spawn_type (get_turf(get_spawn_turf())) - - if(candidates.len) - var/mob/dead/observer/candidate = pick(candidates) - new_mob.ckey = candidate.ckey - post_spawn(new_mob) + new_mob.ckey = chosen_one.ckey + post_spawn(new_mob) ///BACK FOR REVENGE!!! /datum/shuttle_event/simple_spawner/player_controlled/alien_queen diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index d0734355c5e..178f8cbf3ea 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/modular_nova/master_files/code/modules/clothing/head/monkey_magnification_helmet.dm b/modular_nova/master_files/code/modules/clothing/head/monkey_magnification_helmet.dm index 5b8ed86ec4b..891fe40e31a 100644 --- a/modular_nova/master_files/code/modules/clothing/head/monkey_magnification_helmet.dm +++ b/modular_nova/master_files/code/modules/clothing/head/monkey_magnification_helmet.dm @@ -56,13 +56,13 @@ /obj/item/clothing/head/helmet/monkey_sentience/proc/connect(mob/user) polling = TRUE - var/list/candidates = SSpolling.poll_ghost_candidates_for_mob( + var/list/candidates = SSpolling.poll_ghosts_for_target( "Do you want to play as a mind magnified monkey?", ROLE_MONKEY_HELMET, poll_time = 5 SECONDS, - target_mob = magnification, + checked_target = magnification, ignore_category = POLL_IGNORE_MONKEY_HELMET, - pic_source = magnification, + alert_pic = magnification, role_name_text = "mind magnified [magnification.real_name]", ) polling = FALSE diff --git a/modular_nova/modules/clock_cult/code/scriptures/preservation/summon_marauder.dm b/modular_nova/modules/clock_cult/code/scriptures/preservation/summon_marauder.dm index 956c0e58faa..1e293356055 100644 --- a/modular_nova/modules/clock_cult/code/scriptures/preservation/summon_marauder.dm +++ b/modular_nova/modules/clock_cult/code/scriptures/preservation/summon_marauder.dm @@ -28,7 +28,7 @@ check_jobban = FALSE, poll_time = 10 SECONDS, ignore_category = POLL_IGNORE_CONSTRUCT, - pic_source = /obj/item/clockwork/clockwork_slab, + alert_pic = /obj/item/clockwork/clockwork_slab, role_name_text = "clockwork marauder", ) if(length(candidates)) diff --git a/modular_nova/modules/contractor/code/datums/midround/event.dm b/modular_nova/modules/contractor/code/datums/midround/event.dm index f60f93834a3..d708b0ee5e1 100644 --- a/modular_nova/modules/contractor/code/datums/midround/event.dm +++ b/modular_nova/modules/contractor/code/datums/midround/event.dm @@ -15,7 +15,7 @@ var/list/candidates = SSpolling.poll_ghost_candidates( check_jobban = ROLE_DRIFTING_CONTRACTOR, role = ROLE_DRIFTING_CONTRACTOR, - pic_source = /obj/item/melee/baton/telescopic/contractor_baton, + alert_pic = /obj/item/melee/baton/telescopic/contractor_baton, role_name_text = "drifting contractor", ) if(!length(candidates)) diff --git a/modular_nova/modules/cortical_borer/code/cortical_borer_antag.dm b/modular_nova/modules/cortical_borer/code/cortical_borer_antag.dm index c21a2ced2b4..213c4434242 100644 --- a/modular_nova/modules/cortical_borer/code/cortical_borer_antag.dm +++ b/modular_nova/modules/cortical_borer/code/cortical_borer_antag.dm @@ -131,7 +131,7 @@ check_jobban = FALSE, poll_time = 10 SECONDS, ignore_category = POLL_IGNORE_CORTICAL_BORER, - pic_source = /obj/item/borer_egg, + alert_pic = /obj/item/borer_egg, role_name_text = "cortical borer", ) if(!length(candidates)) diff --git a/modular_nova/modules/cortical_borer/code/evolution/evolution_things/empowered_egg.dm b/modular_nova/modules/cortical_borer/code/evolution/evolution_things/empowered_egg.dm index e1c12846835..5d2d379799f 100644 --- a/modular_nova/modules/cortical_borer/code/evolution/evolution_things/empowered_egg.dm +++ b/modular_nova/modules/cortical_borer/code/evolution/evolution_things/empowered_egg.dm @@ -42,7 +42,7 @@ check_jobban = FALSE, poll_time = 10 SECONDS, ignore_category = POLL_IGNORE_CORTICAL_BORER, - pic_source = /obj/item/borer_egg/empowered, + alert_pic = /obj/item/borer_egg/empowered, role_name_text = "empowered cortical borer", ) if(!length(candidates)) diff --git a/modular_nova/modules/goofsec/code/sol_fed.dm b/modular_nova/modules/goofsec/code/sol_fed.dm index 201b590a32f..50ffb3a116a 100644 --- a/modular_nova/modules/goofsec/code/sol_fed.dm +++ b/modular_nova/modules/goofsec/code/sol_fed.dm @@ -146,7 +146,7 @@ GLOBAL_LIST_INIT(call911_do_and_do_not, list( var/list/candidates = SSpolling.poll_ghost_candidates( poll_question, check_jobban = ROLE_DEATHSQUAD, - pic_source = /obj/item/solfed_reporter, + alert_pic = /obj/item/solfed_reporter, role_name_text = cops_to_send::name, ) @@ -586,7 +586,7 @@ GLOBAL_LIST_INIT(call911_do_and_do_not, list( var/list/candidates = SSpolling.poll_ghost_candidates( ghost_poll_msg, jobban_to_check, - pic_source = /obj/item/solfed_reporter, + alert_pic = /obj/item/solfed_reporter, role_name_text = summoned_type, ) diff --git a/modular_nova/modules/mutants/code/mutant_component.dm b/modular_nova/modules/mutants/code/mutant_component.dm index 025efeff998..52ce50e1132 100644 --- a/modular_nova/modules/mutants/code/mutant_component.dm +++ b/modular_nova/modules/mutants/code/mutant_component.dm @@ -156,9 +156,9 @@ /datum/component/mutant_infection/proc/regenerate() if(!host.mind) - var/list/candidates = SSpolling.poll_ghost_candidates_for_mob("Do you want to play as a mutant([host.name])?", - target_mob = host, - pic_source = host, + var/list/candidates = SSpolling.poll_ghosts_for_target("Do you want to play as a mutant([host.name])?", + checked_target = host, + alert_pic = host, role_name_text = "mutant [host.name]", ) if(!candidates.len) diff --git a/modular_nova/modules/oneclickantag/code/oneclickantag.dm b/modular_nova/modules/oneclickantag/code/oneclickantag.dm index 8c88de43768..dac87f762cf 100644 --- a/modular_nova/modules/oneclickantag/code/oneclickantag.dm +++ b/modular_nova/modules/oneclickantag/code/oneclickantag.dm @@ -201,7 +201,7 @@ If anyone can figure out how to get Obsessed to work I would be very appreciativ var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates( "Do you wish to be considered for the position of a Wizard Foundation 'diplomat'?", role = ROLE_WIZARD, - pic_source = /obj/item/clothing/head/wizard, + alert_pic = /obj/item/clothing/head/wizard, role_name_text = "wizard", ) var/mob/living/carbon/human/target @@ -222,7 +222,7 @@ If anyone can figure out how to get Obsessed to work I would be very appreciativ "Do you wish to be considered for a nuke team being sent in?", role = ROLE_OPERATIVE, poll_time = 30 SECONDS, - pic_source = /obj/structure/sign/poster/contraband/gorlex_recruitment, + alert_pic = /obj/structure/sign/poster/contraband/gorlex_recruitment, role_name_text = "syndicate operative", ) var/list/mob/dead/observer/chosen = list() diff --git a/tgstation.dme b/tgstation.dme index 268f7098ab3..92a9016dbd0 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1230,7 +1230,6 @@ #include "code\datums\components\omen.dm" #include "code\datums\components\on_hit_effect.dm" #include "code\datums\components\onwear_mood.dm" -#include "code\datums\components\orbit_poll.dm" #include "code\datums\components\orbiter.dm" #include "code\datums\components\overlay_lighting.dm" #include "code\datums\components\palette.dm"