/datum/game_mode // this includes admin-appointed traitors and multitraitors. Easy! var/list/datum/mind/traitors = list() var/list/datum/mind/implanter = list() var/list/datum/mind/implanted = list() var/datum/mind/exchange_red var/datum/mind/exchange_blue /datum/game_mode/traitor name = "traitor" config_tag = "traitor" restricted_jobs = list("Cyborg")//They are part of the AI if he is traitor so are they, they use to get double chances protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Internal Affairs Agent", "Captain", "Blueshield", "Nanotrasen Representative", "Security Pod Pilot", "Magistrate", "Internal Affairs Agent", "Brig Physician", "Nanotrasen Navy Officer", "Special Operations Officer")//AI", Currently out of the list as malf does not work for shit required_players = 0 required_enemies = 1 recommended_enemies = 4 var/traitors_possible = 4 //hard limit on traitors if scaling is turned off var/const/traitor_scaling_coeff = 5.0 //how much does the amount of players get divided by to determine traitors /datum/game_mode/traitor/announce() to_chat(world, "The current game mode is - Traitor!") to_chat(world, "There is a syndicate traitor on the station. Do not let the traitor succeed!") /datum/game_mode/traitor/pre_setup() if(config.protect_roles_from_antagonist) restricted_jobs += protected_jobs var/list/possible_traitors = get_players_for_role(ROLE_TRAITOR) // stop setup if no possible traitors if(!possible_traitors.len) return 0 var/num_traitors = 1 if(config.traitor_scaling) num_traitors = max(1, round((num_players())/(traitor_scaling_coeff))) else num_traitors = max(1, min(num_players(), traitors_possible)) for(var/j = 0, j < num_traitors, j++) if(!possible_traitors.len) break var/datum/mind/traitor = pick(possible_traitors) traitors += traitor traitor.special_role = "traitor" var/datum/mindslaves/slaved = new() slaved.masters += traitor traitor.som = slaved //we MIGT want to mindslave someone traitor.restricted_roles = restricted_jobs possible_traitors.Remove(traitor) if(!traitors.len) return 0 return 1 /datum/game_mode/traitor/post_setup() for(var/datum/mind/traitor in traitors) forge_traitor_objectives(traitor) spawn(rand(10,100)) finalize_traitor(traitor) greet_traitor(traitor) modePlayer += traitors ..() /datum/game_mode/proc/forge_traitor_objectives(datum/mind/traitor) if(istype(traitor.current, /mob/living/silicon)) var/objective_count = 0 if(prob(30)) var/special_pick = rand(1,2) switch(special_pick) if(1) var/datum/objective/block/block_objective = new block_objective.owner = traitor traitor.objectives += block_objective objective_count++ if(2) //Protect and strand a target var/datum/objective/protect/yandere_one = new yandere_one.owner = traitor traitor.objectives += yandere_one yandere_one.find_target() objective_count++ var/datum/objective/maroon/yandere_two = new yandere_two.owner = traitor yandere_two.target = yandere_one.target traitor.objectives += yandere_two objective_count++ for(var/i = objective_count, i < config.traitor_objectives_amount, i++) var/datum/objective/assassinate/kill_objective = new kill_objective.owner = traitor kill_objective.find_target() traitor.objectives += kill_objective var/datum/objective/survive/survive_objective = new survive_objective.owner = traitor traitor.objectives += survive_objective else var/is_hijacker = prob(10) var/martyr_chance = prob(20) var/objective_count = is_hijacker //Hijacking counts towards number of objectives if(!exchange_blue && traitors.len >= 8) //Set up an exchange if there are enough traitors if(!exchange_red) exchange_red = traitor else exchange_blue = traitor assign_exchange_role(exchange_red) assign_exchange_role(exchange_blue) objective_count += 1 //Exchange counts towards number of objectives var/list/active_ais = active_ais() for(var/i = objective_count, i < config.traitor_objectives_amount, i++) if(prob(50)) if(active_ais.len && prob(100/player_list.len)) var/datum/objective/destroy/destroy_objective = new destroy_objective.owner = traitor destroy_objective.find_target() traitor.objectives += destroy_objective else if(prob(5)) var/datum/objective/debrain/debrain_objective = new debrain_objective.owner = traitor debrain_objective.find_target() traitor.objectives += debrain_objective else if(prob(30)) var/datum/objective/maroon/maroon_objective = new maroon_objective.owner = traitor maroon_objective.find_target() traitor.objectives += maroon_objective else var/datum/objective/assassinate/kill_objective = new kill_objective.owner = traitor kill_objective.find_target() traitor.objectives += kill_objective else var/datum/objective/steal/steal_objective = new steal_objective.owner = traitor steal_objective.find_target() traitor.objectives += steal_objective if(is_hijacker && objective_count <= config.traitor_objectives_amount) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount if(!(locate(/datum/objective/hijack) in traitor.objectives)) var/datum/objective/hijack/hijack_objective = new hijack_objective.owner = traitor traitor.objectives += hijack_objective return var/martyr_compatibility = 1 //You can't succeed in stealing if you're dead. for(var/datum/objective/O in traitor.objectives) if(!O.martyr_compatible) martyr_compatibility = 0 break if(martyr_compatibility && martyr_chance) var/datum/objective/die/martyr_objective = new martyr_objective.owner = traitor traitor.objectives += martyr_objective return else if(!(locate(/datum/objective/escape) in traitor.objectives)) var/datum/objective/escape/escape_objective = new escape_objective.owner = traitor traitor.objectives += escape_objective return /datum/game_mode/proc/greet_traitor(var/datum/mind/traitor) to_chat(traitor.current, "You are the traitor.") var/obj_count = 1 for(var/datum/objective/objective in traitor.objectives) to_chat(traitor.current, "Objective #[obj_count]: [objective.explanation_text]") obj_count++ return /datum/game_mode/proc/finalize_traitor(var/datum/mind/traitor) if(istype(traitor.current, /mob/living/silicon)) add_law_zero(traitor.current) else equip_traitor(traitor.current) return /datum/game_mode/traitor/declare_completion() ..() return//Traitors will be checked as part of check_extra_completion. Leaving this here as a reminder. /datum/game_mode/traitor/process() // Make sure all objectives are processed regularly, so that objectives // which can be checked mid-round are checked mid-round. for(var/datum/mind/traitor_mind in traitors) for(var/datum/objective/objective in traitor_mind.objectives) objective.check_completion() return 0 /datum/game_mode/proc/give_codewords(mob/living/traitor_mob) to_chat(traitor_mob, "The Syndicate provided you with the following information on how to identify their agents:") to_chat(traitor_mob, "Code Phrase: [syndicate_code_phrase]") to_chat(traitor_mob, "Code Response: [syndicate_code_response]") traitor_mob.mind.store_memory("Code Phrase: [syndicate_code_phrase]") traitor_mob.mind.store_memory("Code Response: [syndicate_code_response]") to_chat(traitor_mob, "Use the code words in the order provided, during regular conversation, to identify other agents. Proceed with caution, however, as everyone is a potential foe.") /datum/game_mode/proc/add_law_zero(mob/living/silicon/ai/killer) var/law = "Accomplish your objectives at all costs." var/law_borg = "Accomplish your AI's objectives at all costs." to_chat(killer, "Your laws have been changed!") killer.set_zeroth_law(law, law_borg) to_chat(killer, "New law: 0. [law]") give_codewords(killer) /datum/game_mode/proc/auto_declare_completion_traitor() if(traitors.len) var/text = "The traitors were:" for(var/datum/mind/traitor in traitors) var/traitorwin = 1 text += "
[traitor.key] was [traitor.name] (" if(traitor.current) if(traitor.current.stat == DEAD) text += "died" else text += "survived" if(traitor.current.real_name != traitor.name) text += " as [traitor.current.real_name]" else text += "body destroyed" text += ")" var/TC_uses = 0 var/uplink_true = 0 var/purchases = "" for(var/obj/item/device/uplink/H in world_uplinks) if(H && H.uplink_owner && H.uplink_owner==traitor.key) TC_uses += H.used_TC uplink_true=1 purchases += H.purchase_log if(uplink_true) text += " (used [TC_uses] TC) [purchases]" if(traitor.objectives && traitor.objectives.len)//If the traitor had no objectives, don't need to process this. var/count = 1 for(var/datum/objective/objective in traitor.objectives) if(objective.check_completion()) text += "
Objective #[count]: [objective.explanation_text] Success!" feedback_add_details("traitor_objective","[objective.type]|SUCCESS") else text += "
Objective #[count]: [objective.explanation_text] Fail." feedback_add_details("traitor_objective","[objective.type]|FAIL") traitorwin = 0 count++ var/special_role_text if(traitor.special_role) special_role_text = lowertext(traitor.special_role) else special_role_text = "antagonist" if(traitorwin) text += "
The [special_role_text] was successful!" feedback_add_details("traitor_success","SUCCESS") else text += "
The [special_role_text] has failed!" feedback_add_details("traitor_success","FAIL") to_chat(world, text) return 1 /datum/game_mode/proc/equip_traitor(mob/living/carbon/human/traitor_mob, var/safety = 0) if(!istype(traitor_mob)) return . = 1 if(traitor_mob.mind) if(traitor_mob.mind.assigned_role == "Clown") to_chat(traitor_mob, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") traitor_mob.mutations.Remove(CLUMSY) // find a radio! toolbox(es), backpack, belt, headset var/obj/item/R = locate(/obj/item/device/pda) in traitor_mob.contents //Hide the uplink in a PDA if available, otherwise radio if(!R) R = locate(/obj/item/device/radio) in traitor_mob.contents if(!R) to_chat(traitor_mob, "Unfortunately, the Syndicate wasn't able to get you a radio.") . = 0 else if(istype(R, /obj/item/device/radio)) // generate list of radio freqs var/obj/item/device/radio/target_radio = R var/freq = PUBLIC_LOW_FREQ var/list/freqlist = list() while(freq <= PUBLIC_HIGH_FREQ) if(freq < 1451 || freq > 1459) freqlist += freq freq += 2 if((freq % 2) == 0) freq += 1 freq = freqlist[rand(1, freqlist.len)] var/obj/item/device/uplink/hidden/T = new(R) target_radio.hidden_uplink = T T.uplink_owner = "[traitor_mob.key]" target_radio.traitor_frequency = freq to_chat(traitor_mob, "The Syndicate have cunningly disguised a Syndicate Uplink as your [R.name] [T.loc]. Simply dial the frequency [format_frequency(freq)] to unlock its hidden features.") traitor_mob.mind.store_memory("Radio Freq: [format_frequency(freq)] ([R.name] [T.loc]).") else if(istype(R, /obj/item/device/pda)) // generate a passcode if the uplink is hidden in a PDA var/pda_pass = "[rand(100,999)] [pick("Alpha","Bravo","Delta","Omega")]" var/obj/item/device/uplink/hidden/T = new(R) R.hidden_uplink = T T.uplink_owner = "[traitor_mob.key]" var/obj/item/device/pda/P = R P.lock_code = pda_pass to_chat(traitor_mob, "The Syndicate have cunningly disguised a Syndicate Uplink as your [R.name] [T.loc]. Simply enter the code \"[pda_pass]\" into the ringtone select to unlock its hidden features.") traitor_mob.mind.store_memory("Uplink Passcode: [pda_pass] ([R.name] [T.loc]).") if(!safety)//If they are not a rev. Can be added on to. give_codewords(traitor_mob) // Tell them about people they might want to contact. var/mob/living/carbon/human/M = get_nt_opposed() 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]") /datum/game_mode/proc/update_traitor_icons_added(datum/mind/traitor_mind) var/datum/atom_hud/antag/tatorhud = huds[ANTAG_HUD_TRAITOR] //var/ref = "\ref[traitor_mind]" tatorhud.join_hud(traitor_mind.current) set_antag_hud(traitor_mind.current, "hudsyndicate") /datum/game_mode/proc/update_traitor_icons_removed(datum/mind/traitor_mind) var/datum/atom_hud/antag/tatorhud = huds[ANTAG_HUD_TRAITOR] tatorhud.leave_hud(traitor_mind.current) set_antag_hud(traitor_mind.current, null) /datum/game_mode/proc/remove_traitor_mind(datum/mind/traitor_mind, datum/mind/head) //var/list/removal var/ref = "\ref[head]" if(ref in implanter) implanter[ref] -= traitor_mind implanted -= traitor_mind traitors -= traitor_mind if(traitor_mind.som) var/datum/mindslaves/slaved = traitor_mind.som slaved.serv -= traitor_mind traitor_mind.special_role = null traitor_mind.som = null slaved.leave_serv_hud(traitor_mind) for(var/datum/objective/protect/mindslave/MS in traitor_mind.objectives) traitor_mind.objectives -= MS update_traitor_icons_removed(traitor_mind) to_chat(traitor_mind.current, "You are no longer a mindslave; you have complete and free control of your own faculties, once more!") /datum/game_mode/proc/assign_exchange_role(var/datum/mind/owner) //set faction var/faction = "red" if(owner == exchange_blue) faction = "blue" //Assign objectives var/datum/objective/steal/exchange/exchange_objective = new exchange_objective.set_faction(faction,((faction == "red") ? exchange_blue : exchange_red)) exchange_objective.owner = owner owner.objectives += exchange_objective if(prob(20)) var/datum/objective/steal/exchange/backstab/backstab_objective = new backstab_objective.set_faction(faction) backstab_objective.owner = owner owner.objectives += backstab_objective //Spawn and equip documents var/mob/living/carbon/human/mob = owner.current var/obj/item/weapon/folder/syndicate/folder if(owner == exchange_red) folder = new/obj/item/weapon/folder/syndicate/red(mob.locs) else folder = new/obj/item/weapon/folder/syndicate/blue(mob.locs) var/list/slots = list ( "backpack" = slot_in_backpack, "left pocket" = slot_l_store, "right pocket" = slot_r_store, "left hand" = slot_l_hand, "right hand" = slot_r_hand, ) var/where = "At your feet" var/equipped_slot = mob.equip_in_one_of_slots(folder, slots) if(equipped_slot) where = "In your [equipped_slot]" to_chat(mob, "

[where] is a folder containing secret documents that another Syndicate group wants. We have set up a meeting with one of their agents on station to make an exchange. Exercise extreme caution as they cannot be trusted and may be hostile.
") mob.update_icons()