/datum/game_mode
// this includes admin-appointed traitors and multitraitors. Easy!
var/list/datum/mind/traitors = list()
/datum/game_mode/traitor
name = "traitor"
config_tag = "traitor"
required_players = 0
var/const/prob_int_murder_target = 50 // intercept names the assassination target half the time
var/const/prob_right_murder_target_l = 25 // lower bound on probability of naming right assassination target
var/const/prob_right_murder_target_h = 50 // upper bound on probability of naimg the right assassination target
var/const/prob_int_item = 50 // intercept names the theft target half the time
var/const/prob_right_item_l = 25 // lower bound on probability of naming right theft target
var/const/prob_right_item_h = 50 // upper bound on probability of naming the right theft target
var/const/prob_int_sab_target = 50 // intercept names the sabotage target half the time
var/const/prob_right_sab_target_l = 25 // lower bound on probability of naming right sabotage target
var/const/prob_right_sab_target_h = 50 // upper bound on probability of naming right sabotage target
var/const/prob_right_killer_l = 25 //lower bound on probability of naming the right operative
var/const/prob_right_killer_h = 50 //upper bound on probability of naming the right operative
var/const/prob_right_objective_l = 25 //lower bound on probability of determining the objective correctly
var/const/prob_right_objective_h = 50 //upper bound on probability of determining the objective correctly
/*
var/const/laser = 1
var/const/hand_tele = 2
var/const/plasma_bomb = 3
var/const/jetpack = 4
var/const/captain_card = 5
var/const/captain_suit = 6
var/const/destroy_plasma = 1
var/const/destroy_ai = 2
var/const/kill_monkeys = 3
var/const/cut_power = 4
var/const/percentage_plasma_destroy = 70 // what percentage of the plasma tanks you gotta destroy
var/const/percentage_station_cut_power = 80 // what percentage of the tiles have to have power cut
var/const/percentage_station_evacuate = 80 // what percentage of people gotta leave - you also gotta change the objective in the traitor menu
*/
var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds)
var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds)
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()
world << "The current game mode is - Traitor!"
world << "There is a syndicate traitor on the station. Do not let the traitor succeed!"
/*/datum/game_mode/traitor/can_start()
for(var/mob/new_player/P in world)
if(P.client && P.ready && !jobban_isbanned(P, "Syndicate"))
return 1
return 0*/
/datum/game_mode/traitor/pre_setup()
var/list/possible_traitors = get_players_for_role(BE_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))
// log_game("Number of traitors: [num_traitors]")
// message_admins("Players counted: [num_players] Number of traitors chosen: [num_traitors]")
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"
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
spawn (rand(waittime_l, waittime_h))
send_intercept()
..()
return 1
/datum/game_mode/proc/forge_traitor_objectives(var/datum/mind/traitor)
if(istype(traitor.current, /mob/living/silicon))
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
if(prob(10))
var/datum/objective/block/block_objective = new
block_objective.owner = traitor
traitor.objectives += block_objective
else
switch(rand(1,100))
if(1 to 50)
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
switch(rand(1,100))
if(1 to 90)
if (!(locate(/datum/objective/escape) in traitor.objectives))
var/datum/objective/escape/escape_objective = new
escape_objective.owner = traitor
traitor.objectives += escape_objective
else
if (!(locate(/datum/objective/hijack) in traitor.objectives))
var/datum/objective/hijack/hijack_objective = new
hijack_objective.owner = traitor
traitor.objectives += hijack_objective
return
/datum/game_mode/proc/greet_traitor(var/datum/mind/traitor)
traitor.current << "You are the traitor."
var/obj_count = 1
for(var/datum/objective/objective in traitor.objectives)
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/proc/add_law_zero(mob/living/silicon/ai/killer)
var/law = "Accomplish your objectives at all costs."
killer << "Your laws have been changed!"
killer.set_zeroth_law(law)
killer << "New law: 0. [law]"
//Begin code phrase.
killer << "The Syndicate provided you with the following information on how to identify their agents:"
if(prob(80))
killer << "\red Code Phrase: \black [syndicate_code_phrase]"
killer.mind.store_memory("Code Phrase: [syndicate_code_phrase]")
else
killer << "Unfortunetly, the Syndicate did not provide you with a code phrase."
if(prob(80))
killer << "\red Code Response: \black [syndicate_code_response]"
killer.mind.store_memory("Code Response: [syndicate_code_response]")
else
killer << "Unfortunetly, the Syndicate did not provide you with a code response."
killer << "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."
//End code phrase.
/datum/game_mode/proc/auto_declare_completion_traitor()
for(var/datum/mind/traitor in traitors)
var/traitor_name
if(traitor.current)
if(traitor.current == traitor.original)
traitor_name = "[traitor.current.real_name] (played by [traitor.key])"
else if (traitor.original)
traitor_name = "[traitor.current.real_name] (originally [traitor.original.real_name]) (played by [traitor.key])"
else
traitor_name = "[traitor.current.real_name] (original character destroyed) (played by [traitor.key])"
else
traitor_name = "[traitor.key] (character destroyed)"
var/special_role_text = traitor.special_role?(lowertext(traitor.special_role)):"antagonist"
world << "The [special_role_text] was [traitor_name]"
if(traitor.objectives.len)//If the traitor had no objectives, don't need to process this.
var/traitorwin = 1
var/count = 1
for(var/datum/objective/objective in traitor.objectives)
if(objective.check_completion())
world << "Objective #[count]: [objective.explanation_text] \green Success"
else
world << "Objective #[count]: [objective.explanation_text] \red Failed"
traitorwin = 0
count++
if(traitorwin)
world << "The [special_role_text] was successful!"
else
world << "The [special_role_text] has failed!"
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")
traitor_mob << "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself."
traitor_mob.mutations &= ~CLOWN
// find a radio! toolbox(es), backpack, belt, headset
var/loc = ""
var/obj/item/device/R = null //Hide the uplink in a PDA if available, otherwise radio
if (!R && istype(traitor_mob.belt, /obj/item/device/pda))
R = traitor_mob.belt
loc = "on your belt"
if (!R && istype(traitor_mob.wear_id, /obj/item/device/pda))
R = traitor_mob.wear_id
loc = "on your jumpsuit"
if (!R && istype(traitor_mob.wear_id, /obj/item/device/pda))
R = traitor_mob.wear_id
loc = "on your jumpsuit"
if (!R && istype(traitor_mob.l_hand, /obj/item/weapon/storage))
var/obj/item/weapon/storage/S = traitor_mob.l_hand
var/list/L = S.return_inv()
for (var/obj/item/device/radio/foo in L)
R = foo
loc = "in the [S.name] in your left hand"
break
if (!R && istype(traitor_mob.r_hand, /obj/item/weapon/storage))
var/obj/item/weapon/storage/S = traitor_mob.r_hand
var/list/L = S.return_inv()
for (var/obj/item/device/radio/foo in L)
R = foo
loc = "in the [S.name] in your right hand"
break
if (!R && istype(traitor_mob.back, /obj/item/weapon/storage))
var/obj/item/weapon/storage/S = traitor_mob.back
var/list/L = S.return_inv()
for (var/obj/item/device/radio/foo in L)
R = foo
loc = "in the [S.name] on your back"
break
if (!R && traitor_mob.w_uniform && istype(traitor_mob.belt, /obj/item/device/radio))
R = traitor_mob.belt
loc = "on your belt"
if (!R && istype(traitor_mob.ears, /obj/item/device/radio))
R = traitor_mob.ears
loc = "on your head"
if (!R)
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/freq = 1441
var/list/freqlist = list()
while (freq <= 1489)
if (freq < 1451 || freq > 1459)
freqlist += freq
freq += 2
if ((freq % 2) == 0)
freq += 1
freq = freqlist[rand(1, freqlist.len)]
var/obj/item/weapon/syndicate_uplink/T = new /obj/item/weapon/syndicate_uplink(R)
R:traitorradio = T
R:traitor_frequency = freq
T.name = R.name
T.icon_state = R.icon_state
T.origradio = R
traitor_mob << "The Syndicate have cunningly disguised a Syndicate Uplink as your [R.name] [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] [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/weapon/integrated_uplink/T = new /obj/item/weapon/integrated_uplink(R)
R:uplink = T
T.lock_code = pda_pass
T.hostpda = R
traitor_mob << "The Syndicate have cunningly disguised a Syndicate Uplink as your [R.name] [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] [loc]).")
//Begin code phrase.
if(!safety)//If they are not a rev. Can be added on to.
traitor_mob << "The Syndicate provided you with the following information on how to identify other agents:"
if(prob(80))
traitor_mob << "\red Code Phrase: \black [syndicate_code_phrase]"
traitor_mob.mind.store_memory("Code Phrase: [syndicate_code_phrase]")
else
traitor_mob << "Unfortunetly, the Syndicate did not provide you with a code phrase."
if(prob(80))
traitor_mob << "\red Code Response: \black [syndicate_code_response]"
traitor_mob.mind.store_memory("Code Response: [syndicate_code_response]")
else
traitor_mob << "Unfortunetly, the Syndicate did not provide you with a code response."
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."
//End code phrase.