diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 59f4b79c84d..8249ba65326 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -37,8 +37,9 @@ 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 + 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,8 @@ ///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() + setup_chumps() + spawn (ROUNDSTART_LOGOUT_REPORT_TIME) display_roundstart_logout_report() @@ -85,6 +88,40 @@ 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) + 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() ///Called by the gameticker @@ -225,7 +262,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 +437,20 @@ 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) + 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)) dudes += man - if(dudes.len == 0) return null + if(dudes.len == 0) + return null return pick(dudes) //Announces objectives/generic antag text. @@ -491,10 +533,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 +546,34 @@ 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() + + +/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 cd6dd80876b..6cb2956d3ee 100644 --- a/code/game/gamemodes/intercept_report.dm +++ b/code/game/gamemodes/intercept_report.dm @@ -109,8 +109,16 @@ /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) + 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 + 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..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)) @@ -345,6 +348,14 @@ 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/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 + ..(M) + /datum/game_mode/proc/remove_traitor(datum/mind/traitor_mind) if(traitor_mind in traitors) @@ -355,8 +366,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)