From 0ad6fec5b1c20dda7f1e45332876f8a265be66dc Mon Sep 17 00:00:00 2001 From: FalseIncarnate Date: Wed, 22 Mar 2017 20:36:24 -0400 Subject: [PATCH 1/3] Collaborators are no longer clueless about Syndicate Alternative to #6829 The Syndicate no longer leaves their potential collaborators in absolute darkness about their usefulness. Collaborators are notified of their potential use, though in a vague way so as not to compromise the identities of any agents directly. - Potential collaborators get messages informing them that they are still not antags, but that they may be asked to assist, when they are assigned to a new traitor. - Potential collaborators get a SINGLE code word and code response so their clandestine friend can attempt to communicate with them with more subtlety than "hey, im a traitor, want to help?" - They are only given 1 word set so they can't just inform security and the AI of all the codewords alone. Same reason they aren't given a name of the traitor they might be asked to assist. The intercept report (currently disabled) now only lists suspects that actually CAN be the antag (no more listing the chaplain as a potential cultist, the HoS as a potential traitor, or that IPC in atmos as a possible changeling). Potential collaborators can no longer be characters in roles that are restricted from being traitors. So no more "Potential collaborator: The captain", as funny as that may have been. :cl: tweak: Potential collaborators for traitors now are informed they are potentially a collaborator for a potential increase in them potentially helping the traitors potentially do potentially bad things. Potentially. rscadd: Potential collaborators are given a single code word and response set so they can discretely find out that their best friend is a filthy traitor. /:cl: --- code/game/gamemodes/game_mode.dm | 22 ++++++++++------- code/game/gamemodes/intercept_report.dm | 11 +++++++-- code/game/gamemodes/traitor/traitor.dm | 32 +++++++++++++++++++++++-- 3 files changed, 52 insertions(+), 13 deletions(-) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 59f4b79c84d..075161c89ca 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -37,7 +37,7 @@ var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) var/list/player_draft_log = list() var/list/datum/mind/xenos = list() - + var/list/datum/station_goal/station_goals = list() // A list of all station goals for this game mode /datum/game_mode/proc/announce() //to be calles when round starts @@ -225,7 +225,7 @@ /datum/game_mode/proc/check_win() //universal trigger to be called at mob death, nuke explosion, etc. To be called from everywhere. return 0 - + /datum/game_mode/proc/get_players_for_role(var/role, override_jobbans=0) var/list/players = list() var/list/candidates = list() @@ -400,15 +400,19 @@ proc/display_roundstart_logout_report() to_chat(M, msg) -proc/get_nt_opposed() +/proc/get_nt_opposed() var/list/dudes = list() for(var/mob/living/carbon/human/man in player_list) if(man.client) + //don't try picking someone like the captain or a security officer for potential collaborators, even if they ARE opposed to Nanotrasen for some reason + if(man.mind && man.mind.assigned_role && !((man.mind.assigned_role in ticker.mode.protected_jobs) || (man.mind.assigned_role in ticker.mode.restricted_jobs))) + continue if(man.client.prefs.nanotrasen_relation == "Opposed") dudes += man else if(man.client.prefs.nanotrasen_relation == "Skeptical" && prob(50)) dudes += man - if(dudes.len == 0) return null + if(dudes.len == 0) + return null return pick(dudes) //Announces objectives/generic antag text. @@ -491,10 +495,10 @@ proc/get_nt_opposed() var/datum/station_goal/picked = pick_n_take(possible) goal_weights += initial(picked.weight) station_goals += new picked - - if(station_goals.len) + + if(station_goals.len) send_station_goals_message() - + /datum/game_mode/proc/send_station_goals_message() var/message_text = "
" message_text += "

[command_name()] Orders


" @@ -504,10 +508,10 @@ proc/get_nt_opposed() G.on_report() message_text += G.get_report() message_text += "
" - + print_command_report(message_text, "[command_name()] Orders") /datum/game_mode/proc/declare_station_goal_completion() for(var/V in station_goals) var/datum/station_goal/G = V - G.print_result() \ No newline at end of file + G.print_result() \ No newline at end of file diff --git a/code/game/gamemodes/intercept_report.dm b/code/game/gamemodes/intercept_report.dm index cd6dd80876b..29803cf34dc 100644 --- a/code/game/gamemodes/intercept_report.dm +++ b/code/game/gamemodes/intercept_report.dm @@ -109,8 +109,15 @@ /datum/intercept_text/proc/get_suspect() var/list/dudes = list() - for(var/mob/living/carbon/human/man in player_list) if(man.client && man.client.prefs.nanotrasen_relation == "Opposed") - dudes += man + for(var/mob/living/carbon/human/man in player_list) + if(man.client && man.client.prefs.nanotrasen_relation == "Opposed") + //don't include suspects who can't possibly be the antag based on their job (no suspecting the captain of being a damned dirty tator) + if(man.mind && man.mind.assigned_role && !((man.mind.assigned_role in ticker.mode.protected_jobs) || (man.mind.assigned_role in ticker.mode.restricted_jobs))) + return + //don't include suspects who can't possibly be the antag based on their species (no suspecting the machines of being sneaky changelings) + if(man.get_species() in ticker.mode.protected_species) + return + dudes += man for(var/i = 0, i < max(player_list.len/10,2), i++) dudes += pick(player_list) return pick(dudes) diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index 371aef6c6a0..09d014a2afc 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -345,6 +345,34 @@ if(M && M != traitor_mob) to_chat(traitor_mob, "We have received credible reports that [M.real_name] might be willing to help our cause. If you need assistance, consider contacting them.") traitor_mob.mind.store_memory("Potential Collaborator: [M.real_name]") + //let's also inform their contact that they might be called upon, but leave it vague. + inform_collab(M) + +/datum/game_mode/proc/inform_collab(mob/living/carbon/human/M) + if(!M) + return + if(M.mind in traitors) //if you are already a traitor, you already know the codewords and your role, so skip this message. + return + //Mad-libs for their message + var/adjective = pick("strange", "mysterious", "sinister", "un-assuming", "unexpected") + var/action_words = pick("aid the fight against Nanotrasen", "repay a debt", "partake in some mischief", "help overthrow the system", "stick it to the man") + var/organization = pick("Anti-Facist Movement", "Syndicate", "Spessmen for the Protesting of Nanotrasen", "Greytider's Union", "Illuminati (in space)") + //Stuff to give them a single set of code-words + var/list/possible_words = splittext(syndicate_code_phrase, ", ") + var/list/possible_reply = splittext(syndicate_code_response, ", ") + var/index = rand(1, possible_words.len) + var/my_word = possible_words[index] + var/my_reply + if(possible_reply.len < index) //just in case we had a longer code word list than the response list + my_reply = pick(possible_reply) + else + my_reply = possible_reply[index] + + to_chat(M, "You suddenly remember \an [adjective] note you received earlier informing you that a chance to [action_words] may present itself today. An agent of the [organization] may contact you for help.") + to_chat(M, "The note had the words \"[my_word]\" and \"[my_reply]\" written at the bottom, which you memorized just in case.") + to_chat(M, "You are NOT an antagonist, so self-antagging rules still apply to you. Use your good judgement and ahelp if you are unsure of what you are allowed to do.") + M.mind.store_memory("Important Words: \"[my_word]\", \"[my_reply]\"") + /datum/game_mode/proc/remove_traitor(datum/mind/traitor_mind) if(traitor_mind in traitors) @@ -355,8 +383,8 @@ to_chat(traitor_mind.current, "You have been turned into a robot! You are no longer a traitor.") else to_chat(traitor_mind.current, "You have been brainwashed! You are no longer a traitor.") - ticker.mode.update_traitor_icons_removed(traitor_mind) - + ticker.mode.update_traitor_icons_removed(traitor_mind) + /datum/game_mode/proc/update_traitor_icons_added(datum/mind/traitor_mind) var/datum/atom_hud/antag/tatorhud = huds[ANTAG_HUD_TRAITOR] tatorhud.join_hud(traitor_mind.current) From 60096df843a5561a095fb7f3ec2af983c55b86b4 Mon Sep 17 00:00:00 2001 From: FalseIncarnate Date: Thu, 23 Mar 2017 19:42:06 -0400 Subject: [PATCH 2/3] Anti-Scum Safeties All game modes EXCEPT traitor (and it's variants) misinform a number of chumps that they are potential collaborators, to cut down on metagame potential. Traitor modes don't misinform anyone and instead inform the real potential collaborators only to prevent spreading actual codewords to the general public. Maximum number of chumps scales with population, though it is possible to end up with fewer chumps than the maximum based on RNG and the number of people with opposed/skeptical relations. Also fixed some accidentally inverted checks that broke everything, and moved the inform_collab proc to the base game_mode type for organization --- code/game/gamemodes/game_mode.dm | 64 +++++++++++++++++++++++-- code/game/gamemodes/intercept_report.dm | 5 +- code/game/gamemodes/traitor/traitor.dm | 27 ++--------- 3 files changed, 69 insertions(+), 27 deletions(-) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 075161c89ca..e0ef1b480d0 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -39,6 +39,7 @@ var/list/datum/mind/xenos = list() var/list/datum/station_goal/station_goals = list() // A list of all station goals for this game mode + var/list/chumps = list() /datum/game_mode/proc/announce() //to be calles when round starts to_chat(world, "Notice: [src] did not define announce()") @@ -71,6 +72,9 @@ ///post_setup() ///Everyone should now be on the station and have their normal gear. This is the place to give the special roles extra things /datum/game_mode/proc/post_setup() + spawn(30) + setup_chumps() + spawn (ROUNDSTART_LOGOUT_REPORT_TIME) display_roundstart_logout_report() @@ -85,6 +89,35 @@ start_state.count() return 1 +//setup_chumps() +//Prepares fake potential collaborators to cut down on metagaming the round type as being a traitor subtype. Overriden in traitor game modes since they have real collaborators +/datum/game_mode/proc/setup_chumps() + var/max_chumps = 1 + if(config.traitor_scaling) + max_chumps = max(1, round((num_players())/(5))) + else + max_chumps = max(1, min(num_players(), 5)) + var/tries_left = 5 //limits the number of tries so we don't get stuck looping indefinitely. resets on successfully finding a new chump + while(chumps.len < max_chumps) + if(!tries_left) //ran out of unique chumps (or just bad luck with the pick() in get_nt_opposed()) so there may end up being fewer chumps in some rounds. + break + var/mob/living/carbon/human/chump = get_nt_opposed() + if(isnull(chump)) //no possible chumps so just end it here. + break + if(chump in chumps) + tries_left-- //this chump already was picked, try again! + else + chumps += chump + tries_left = 5 //reset our tries since we found a new chump + //make sure we have chumps before we try misinforming them. if we don't make a note of it. + if(!chumps.len) + message_admins("Game mode failed to find ANY chumps. Possible causes: no one is opposed/skeptical, or FalseIncarnate can't code.") + log_admin("Game mode failed to find ANY chumps. Possible causes: no one is opposed/skeptical, or FalseIncarnate can't code.") + return 0 + //we've got chumps! misinform them! + for(var/mob/living/carbon/human/chump in chumps) + inform_collab(chump) + return 1 ///process() ///Called by the gameticker @@ -405,8 +438,9 @@ proc/display_roundstart_logout_report() for(var/mob/living/carbon/human/man in player_list) if(man.client) //don't try picking someone like the captain or a security officer for potential collaborators, even if they ARE opposed to Nanotrasen for some reason - if(man.mind && man.mind.assigned_role && !((man.mind.assigned_role in ticker.mode.protected_jobs) || (man.mind.assigned_role in ticker.mode.restricted_jobs))) - continue + if(man.mind && man.mind.assigned_role) + if((man.mind.assigned_role in ticker.mode.protected_jobs) || (man.mind.assigned_role in ticker.mode.restricted_jobs)) + continue if(man.client.prefs.nanotrasen_relation == "Opposed") dudes += man else if(man.client.prefs.nanotrasen_relation == "Skeptical" && prob(50)) @@ -514,4 +548,28 @@ proc/display_roundstart_logout_report() /datum/game_mode/proc/declare_station_goal_completion() for(var/V in station_goals) var/datum/station_goal/G = V - G.print_result() \ No newline at end of file + G.print_result() + + +/datum/game_mode/proc/inform_collab(mob/living/carbon/human/M) + if(!M) + return + //Mad-libs for their message + var/adjective = pick("strange", "mysterious", "sinister", "un-assuming", "unexpected") + var/action_words = pick("aid the fight against Nanotrasen", "repay a debt", "partake in some mischief", "help overthrow the system", "stick it to the man") + var/organization = pick("Anti-Fascist Movement", "Syndicate", "Spessmen for the Protesting of Nanotrasen", "Greytider's Union", "Illuminati (in space)") + //Stuff to give them a single set of code-words + var/list/possible_words = splittext(syndicate_code_phrase, ", ") + var/list/possible_reply = splittext(syndicate_code_response, ", ") + var/index = rand(1, possible_words.len) + var/my_word = possible_words[index] + var/my_reply + if(possible_reply.len < index) //just in case we had a longer code word list than the response list + my_reply = pick(possible_reply) + else + my_reply = possible_reply[index] + + to_chat(M, "You suddenly remember \an [adjective] note you received earlier informing you that a chance to [action_words] may present itself today. An agent of the [organization] may contact you for help.") + to_chat(M, "The note had the words \"[my_word]\" and \"[my_reply]\" written at the bottom, which you memorized just in case.") + to_chat(M, "You are NOT an antagonist, so self-antagging rules still apply to you. Use your good judgement and ahelp if you are unsure of what you are allowed to do.") + M.mind.store_memory("Important Words: \"[my_word]\", \"[my_reply]\"") diff --git a/code/game/gamemodes/intercept_report.dm b/code/game/gamemodes/intercept_report.dm index 29803cf34dc..6cb2956d3ee 100644 --- a/code/game/gamemodes/intercept_report.dm +++ b/code/game/gamemodes/intercept_report.dm @@ -112,8 +112,9 @@ for(var/mob/living/carbon/human/man in player_list) if(man.client && man.client.prefs.nanotrasen_relation == "Opposed") //don't include suspects who can't possibly be the antag based on their job (no suspecting the captain of being a damned dirty tator) - if(man.mind && man.mind.assigned_role && !((man.mind.assigned_role in ticker.mode.protected_jobs) || (man.mind.assigned_role in ticker.mode.restricted_jobs))) - return + if(man.mind && man.mind.assigned_role) + if((man.mind.assigned_role in ticker.mode.protected_jobs) || (man.mind.assigned_role in ticker.mode.restricted_jobs)) + return //don't include suspects who can't possibly be the antag based on their species (no suspecting the machines of being sneaky changelings) if(man.get_species() in ticker.mode.protected_species) return diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index 09d014a2afc..e60b564f5d0 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -70,6 +70,9 @@ modePlayer += traitors ..() +/datum/game_mode/traitor/setup_chumps() + //since we actually have potential collaborators, we don't prepare any chumps to avoid extra people knowing our codewords. + return /datum/game_mode/proc/forge_traitor_objectives(datum/mind/traitor) if(istype(traitor.current, /mob/living/silicon)) @@ -348,30 +351,10 @@ //let's also inform their contact that they might be called upon, but leave it vague. inform_collab(M) -/datum/game_mode/proc/inform_collab(mob/living/carbon/human/M) - if(!M) - return +/datum/game_mode/traitor/inform_collab(mob/living/carbon/human/M) if(M.mind in traitors) //if you are already a traitor, you already know the codewords and your role, so skip this message. return - //Mad-libs for their message - var/adjective = pick("strange", "mysterious", "sinister", "un-assuming", "unexpected") - var/action_words = pick("aid the fight against Nanotrasen", "repay a debt", "partake in some mischief", "help overthrow the system", "stick it to the man") - var/organization = pick("Anti-Facist Movement", "Syndicate", "Spessmen for the Protesting of Nanotrasen", "Greytider's Union", "Illuminati (in space)") - //Stuff to give them a single set of code-words - var/list/possible_words = splittext(syndicate_code_phrase, ", ") - var/list/possible_reply = splittext(syndicate_code_response, ", ") - var/index = rand(1, possible_words.len) - var/my_word = possible_words[index] - var/my_reply - if(possible_reply.len < index) //just in case we had a longer code word list than the response list - my_reply = pick(possible_reply) - else - my_reply = possible_reply[index] - - to_chat(M, "You suddenly remember \an [adjective] note you received earlier informing you that a chance to [action_words] may present itself today. An agent of the [organization] may contact you for help.") - to_chat(M, "The note had the words \"[my_word]\" and \"[my_reply]\" written at the bottom, which you memorized just in case.") - to_chat(M, "You are NOT an antagonist, so self-antagging rules still apply to you. Use your good judgement and ahelp if you are unsure of what you are allowed to do.") - M.mind.store_memory("Important Words: \"[my_word]\", \"[my_reply]\"") + ..(M) /datum/game_mode/proc/remove_traitor(datum/mind/traitor_mind) From 3d751c45d5775ba3b0e33d5cc0b1edfbb3ef76b2 Mon Sep 17 00:00:00 2001 From: FalseIncarnate Date: Thu, 23 Mar 2017 20:03:27 -0400 Subject: [PATCH 3/3] Anti-Scum Safeties 2 Misinformation is now staggered randomly to throw off even hardier metagamers. --- code/game/gamemodes/game_mode.dm | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index e0ef1b480d0..8249ba65326 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -72,8 +72,7 @@ ///post_setup() ///Everyone should now be on the station and have their normal gear. This is the place to give the special roles extra things /datum/game_mode/proc/post_setup() - spawn(30) - setup_chumps() + setup_chumps() spawn (ROUNDSTART_LOGOUT_REPORT_TIME) display_roundstart_logout_report() @@ -116,7 +115,12 @@ return 0 //we've got chumps! misinform them! for(var/mob/living/carbon/human/chump in chumps) - inform_collab(chump) + if(prob(33)) + spawn(rand(3000, 18000)) //5-30 minute delay to throw off would-be autotraitor metagamers + inform_collab(chump) + else + spawn(rand(10, 100)) //same delay as if the mode were traitor + inform_collab(chump) return 1 ///process()