diff --git a/code/game/gamemodes/traitor/double_agents.dm b/code/game/gamemodes/traitor/double_agents.dm
index 2ee546c7aa..dfe198eeb9 100644
--- a/code/game/gamemodes/traitor/double_agents.dm
+++ b/code/game/gamemodes/traitor/double_agents.dm
@@ -1,6 +1,8 @@
#define PINPOINTER_MINIMUM_RANGE 15
#define PINPOINTER_EXTRA_RANDOM_RANGE 10
#define PINPOINTER_PING_TIME 40
+#define PROB_ACTUAL_TRAITOR 20
+#define TRAITOR_AGENT_ROLE "Syndicate External Affairs Agent"
/datum/game_mode/traitor/internal_affairs
name = "Internal Affairs"
@@ -171,7 +173,10 @@
if(!objective.check_completion())
traitored = FALSE
return
- to_chat(owner.current," All the other agents are dead, and you're the last loose end. Stage a Syndicate terrorist attack to cover up for today's events. You no longer have any limits on collateral damage.")
+ if(owner.special_role == TRAITOR_AGENT_ROLE)
+ to_chat(owner.current," All the loyalist agents are dead, and no more is required of you. Die a glorious death, agent. ")
+ else
+ to_chat(owner.current," All the other agents are dead, and you're the last loose end. Stage a Syndicate terrorist attack to cover up for today's events. You no longer have any limits on collateral damage.")
replace_escape_objective(owner)
@@ -194,7 +199,10 @@
if(objective.stolen)
var/fail_msg = "Your sensors tell you that [objective.target.current.real_name], one of the targets you were meant to have killed, pulled one over on you, and is still alive - do the job properly this time! "
if(traitored)
- fail_msg += " The truth could still slip out! Cease any terrorist actions as soon as possible, unneeded property damage or loss of employee life will lead to your contract being terminated."
+ if(owner.special_role == TRAITOR_AGENT_ROLE)
+ fail_msg += " You no longer have permission to die. "
+ else
+ fail_msg += " The truth could still slip out! Cease any terrorist actions as soon as possible, unneeded property damage or loss of employee life will lead to your contract being terminated."
reinstate_escape_objective(owner)
traitored = FALSE
to_chat(owner.current, fail_msg)
@@ -238,6 +246,10 @@
state.add_steal_targets_timer()
if(!issilicon(traitor.current))
give_pinpointer(traitor)
+ //Optional traitor objective
+ if(prob(PROB_ACTUAL_TRAITOR))
+ traitor.special_role = TRAITOR_AGENT_ROLE
+ forge_single_objective(traitor)
else
..() // Give them standard objectives.
@@ -289,11 +301,18 @@
/datum/game_mode/traitor/internal_affairs/greet_traitor(datum/mind/traitor)
var/crime = pick("distribution of contraband" , "unauthorized erotic action on duty", "embezzlement", "piloting under the influence", "dereliction of duty", "syndicate collaboration", "mutiny", "multiple homicides", "corporate espionage", "recieving bribes", "malpractice", "worship of prohbited life forms", "possession of profane texts", "murder", "arson", "insulting their manager", "grand theft", "conspiracy", "attempting to unionize", "vandalism", "gross incompetence")
- to_chat(traitor.current, "You are the [traitor_name].")
- to_chat(traitor.current, "Your target is suspected of [crime], and you have been tasked with eliminating them by any means necessary to avoid a costly and embarrassing public trial.")
- to_chat(traitor.current, "While you have a license to kill, unneeded property damage or loss of employee life will lead to your contract being terminated.")
- to_chat(traitor.current, "For the sake of plausible deniability, you have been equipped with an array of captured Syndicate weaponry available via uplink.")
- to_chat(traitor.current, "Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.")
+ if(traitor.special_role == TRAITOR_AGENT_ROLE)
+ to_chat(traitor.current, "You are the [TRAITOR_AGENT_ROLE].")
+ to_chat(traitor.current, "Your target has been framed for [crime], and you have been tasked with eliminating them to prevent them defending themselves in court.")
+ to_chat(traitor.current, "Any damage you cause will be a further embarrassment to Nanotrasen, so you have no limits on collateral damage.")
+ to_chat(traitor.current, " You have been provided with a standard uplink to accomplish your task. ")
+ to_chat(traitor.current, "Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.")
+ else
+ to_chat(traitor.current, "You are the [traitor_name].")
+ to_chat(traitor.current, "Your target is suspected of [crime], and you have been tasked with eliminating them by any means necessary to avoid a costly and embarrassing public trial.")
+ to_chat(traitor.current, "While you have a license to kill, unneeded property damage or loss of employee life will lead to your contract being terminated.")
+ to_chat(traitor.current, "For the sake of plausible deniability, you have been equipped with an array of captured Syndicate weaponry available via uplink.")
+ to_chat(traitor.current, "Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.")
traitor.announce_objectives()
@@ -301,6 +320,8 @@
/datum/game_mode/traitor/internal_affairs/give_codewords(mob/living/traitor_mob)
return
+#undef PROB_ACTUAL_TRAITOR
#undef PINPOINTER_EXTRA_RANDOM_RANGE
#undef PINPOINTER_MINIMUM_RANGE
#undef PINPOINTER_PING_TIME
+
diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm
index 4673b572a8..6ad37815ca 100644
--- a/code/game/gamemodes/traitor/traitor.dm
+++ b/code/game/gamemodes/traitor/traitor.dm
@@ -85,40 +85,65 @@
character.make_Traitor()
+/datum/game_mode/proc/forge_single_objective(datum/mind/traitor) //Returns how many objectives are added
+ .=1
+ if(issilicon(traitor.current))
+ var/special_pick = rand(1,4)
+ switch(special_pick)
+ if(1)
+ var/datum/objective/block/block_objective = new
+ block_objective.owner = traitor
+ traitor.objectives += block_objective
+ if(2)
+ var/datum/objective/purge/purge_objective = new
+ purge_objective.owner = traitor
+ traitor.objectives += purge_objective
+ if(3)
+ var/datum/objective/robot_army/robot_objective = new
+ robot_objective.owner = traitor
+ traitor.objectives += robot_objective
+ if(4) //Protect and strand a target
+ var/datum/objective/protect/yandere_one = new
+ yandere_one.owner = traitor
+ traitor.objectives += yandere_one
+ yandere_one.find_target()
+ var/datum/objective/maroon/yandere_two = new
+ yandere_two.owner = traitor
+ yandere_two.target = yandere_one.target
+ yandere_two.update_explanation_text() // normally called in find_target()
+ traitor.objectives += yandere_two
+ .=2
+ else
+ if(prob(50))
+ var/list/active_ais = active_ais()
+ if(active_ais.len && prob(100/GLOB.joined_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(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
+
+
/datum/game_mode/proc/forge_traitor_objectives(datum/mind/traitor)
if(issilicon(traitor.current))
var/objective_count = 0
if(prob(30))
- var/special_pick = rand(1,4)
- switch(special_pick)
- if(1)
- var/datum/objective/block/block_objective = new
- block_objective.owner = traitor
- traitor.objectives += block_objective
- objective_count++
- if(2)
- var/datum/objective/purge/purge_objective = new
- purge_objective.owner = traitor
- traitor.objectives += purge_objective
- objective_count++
- if(3)
- var/datum/objective/robot_army/robot_objective = new
- robot_objective.owner = traitor
- traitor.objectives += robot_objective
- objective_count++
- if(4) //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
- yandere_two.update_explanation_text() // normally called in find_target()
- traitor.objectives += yandere_two
- objective_count++
+ objective_count+=forge_single_objective(traitor)
for(var/i = objective_count, i < config.traitor_objectives_amount, i++)
var/datum/objective/assassinate/kill_objective = new
@@ -142,29 +167,8 @@
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/GLOB.joined_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(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
+ forge_single_objective(traitor)
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))