diff --git a/code/game/gamemodes/autotraitor/autotraitor.dm b/code/game/gamemodes/autotraitor/autotraitor.dm
new file mode 100644
index 00000000000..c163c809d0e
--- /dev/null
+++ b/code/game/gamemodes/autotraitor/autotraitor.dm
@@ -0,0 +1,211 @@
+//This is a beta game mode to test ways to implement an "infinite" traitor round in which more traitors are automatically added in as needed.
+//Automatic traitor adding is complete pending the inevitable bug fixes. Need to add a respawn system to let dead people respawn after 30 minutes or so.
+
+
+/datum/game_mode/traitor/autotraitor
+ name = "AutoTraitor"
+ config_tag = "Extend-A-Traitormongous"
+
+ var/list/possible_traitors
+
+/datum/game_mode/traitor/autotraitor/announce()
+ ..()
+ world << "This is a test bed for theories and methods to implement an infinite traitor round. Traitors will be added to the round automagically as needed.
Expect bugs."
+
+/datum/game_mode/traitor/autotraitor/pre_setup()
+ possible_traitors = get_players_for_role(BE_TRAITOR)
+
+ for(var/mob/new_player/P in world)
+ if(P.client && P.ready)
+ num_players++
+
+ //var/r = rand(5)
+ var/num_traitors = 1
+ var/max_traitors = 1
+ var/traitor_prob = 0
+ max_traitors = round(num_players / 10) + 1
+ traitor_prob = (num_players - (max_traitors - 1) * 10) * 10
+
+ // Stop setup if no possible traitors
+ if(!possible_traitors.len)
+ return 0
+
+ if(config.traitor_scaling)
+ num_traitors = max_traitors - 1 + prob(traitor_prob)
+ log_game("Number of traitors: [num_traitors]")
+ message_admins("Players counted: [num_players] Number of traitors chosen: [num_traitors]")
+ else
+ num_traitors = max(1, min(num_players(), traitors_possible))
+
+
+ for(var/i = 0, i < num_traitors, i++)
+ var/datum/mind/traitor = pick(possible_traitors)
+ traitors += traitor
+ possible_traitors.Remove(traitor)
+
+ for(var/datum/mind/traitor in traitors)
+ if(!traitor || !istype(traitor))
+ traitors.Remove(traitor)
+ continue
+ if(istype(traitor))
+ traitor.special_role = "traitor"
+
+// if(!traitors.len)
+// return 0
+ return 1
+
+
+
+
+/datum/game_mode/traitor/autotraitor/post_setup()
+ ..()
+ for(var/mob/T in world)
+ if(T.mind in possible_traitors)
+ T.be_syndicate = 1
+ abandon_allowed = 1
+ traitorcheckloop()
+
+/datum/game_mode/traitor/autotraitor/proc/traitorcheckloop()
+ spawn(9000)
+ if(emergency_shuttle.departed)
+ return
+ //message_admins("Performing AutoTraitor Check")
+ var/playercount = 0
+ var/traitorcount = 0
+ var/possible_traitors[0]
+ for(var/mob/living/player in world)
+
+ if (player.client && player.stat != 2)
+ playercount += 1
+ if (player.client && player.mind && player.mind.special_role && player.stat != 2)
+ traitorcount += 1
+ if (player.client && player.mind && !player.mind.special_role && player.stat != 2 && player.be_syndicate && !jobban_isbanned(player, "Syndicate"))
+ possible_traitors += player
+ //message_admins("Live Players: [playercount]")
+ //message_admins("Live Traitors: [traitorcount]")
+// message_admins("Potential Traitors:")
+// for(var/mob/living/traitorlist in possible_traitors)
+// message_admins("[traitorlist.real_name]")
+
+// var/r = rand(5)
+// var/target_traitors = 1
+ var/max_traitors = 1
+ var/traitor_prob = 0
+ max_traitors = round(playercount / 10) + 1
+ traitor_prob = (playercount - (max_traitors - 1) * 10) * 5
+ if(traitorcount < max_traitors - 1)
+ traitor_prob += 50
+
+
+ if(traitorcount < max_traitors)
+ //message_admins("Number of Traitors is below maximum. Rolling for new Traitor.")
+ //message_admins("The probability of a new traitor is [traitor_prob]%")
+
+ if(prob(traitor_prob))
+ message_admins("Making a new Traitor.")
+ if(!possible_traitors.len)
+ message_admins("No potential traitors. Cancelling new traitor.")
+ traitorcheckloop()
+ return
+ var/mob/living/newtraitor = pick(possible_traitors)
+ //message_admins("[newtraitor.real_name] is the new Traitor.")
+
+ forge_traitor_objectives(newtraitor.mind)
+ equip_traitor(newtraitor)
+ traitors += newtraitor.mind
+ newtraitor << "\red ATTENTION: \black It is time to pay your debt to the Syndicate..."
+ newtraitor << "You are now a traitor."
+ newtraitor.mind.special_role = "traitor"
+ var/obj_count = 1
+ newtraitor << "\blue Your current objectives:"
+ for(var/datum/objective/objective in newtraitor.mind.objectives)
+ newtraitor << "Objective #[obj_count]: [objective.explanation_text]"
+ obj_count++
+ //else
+ //message_admins("No new traitor being added.")
+ //else
+ //message_admins("Number of Traitors is at maximum. Not making a new Traitor.")
+
+
+/* Old equation. Commenting out.
+ target_traitors = max(1, min(round((playercount + r) / 10, 1), traitors_possible))
+ message_admins("Target Traitor Count is: [target_traitors]")
+
+ if (traitorcount < target_traitors)
+ message_admins("Number of Traitors is below Target. Making a new Traitor.")
+ var/mob/living/newtraitor = pick(possible_traitors)
+ message_admins("[newtraitor.real_name] is the new Traitor.")
+
+ for(var/datum/objective/o in SelectObjectives(newtraitor.mind.assigned_role, newtraitor.mind))
+ o.owner = newtraitor.mind
+ newtraitor.mind.objectives += o
+
+ equip_traitor(newtraitor)
+ traitors += newtraitor.mind
+ newtraitor << "\red ATTENTION: \black It is time to pay your debt to the Syndicate..."
+ newtraitor << "You are now a traitor."
+ newtraitor.mind.special_role = "traitor"
+ var/obj_count = 1
+ newtraitor << "\blue Your current objectives:"
+ for(var/datum/objective/objective in newtraitor.mind.objectives)
+ newtraitor << "Objective #[obj_count]: [objective.explanation_text]"
+ obj_count++
+ else
+ message_admins("Number of Traitors is at Target. No new Traitor.")
+*/
+ traitorcheckloop()
+
+
+
+/datum/game_mode/traitor/autotraitor/latespawn(mob/living/carbon/human/character)
+ ..()
+ if(emergency_shuttle.departed)
+ return
+ //message_admins("Late Join Check")
+ if(character.be_syndicate == 1 && !jobban_isbanned(character, "Syndicate"))
+ //message_admins("Late Joiner has Be Syndicate")
+ //message_admins("Checking number of players")
+ var/playercount = 0
+ var/traitorcount = 0
+ for(var/mob/living/player in world)
+
+ if (player.client && player.stat != 2)
+ playercount += 1
+ if (player.client && player.mind && player.mind.special_role && player.stat != 2)
+ traitorcount += 1
+ //message_admins("Live Players: [playercount]")
+ //message_admins("Live Traitors: [traitorcount]")
+
+ //var/r = rand(5)
+ //var/target_traitors = 1
+ var/max_traitors = 2
+ var/traitor_prob = 0
+ max_traitors = round(playercount / 10) + 1
+ traitor_prob = (playercount - (max_traitors - 1) * 10) * 5
+ if(traitorcount < max_traitors - 1)
+ traitor_prob += 50
+
+ //target_traitors = max(1, min(round((playercount + r) / 10, 1), traitors_possible))
+ //message_admins("Target Traitor Count is: [target_traitors]")
+ if (traitorcount < max_traitors)
+ //message_admins("Number of Traitors is below maximum. Rolling for New Arrival Traitor.")
+ //message_admins("The probability of a new traitor is [traitor_prob]%")
+ if(prob(traitor_prob))
+ message_admins("New traitor roll passed. Making a new Traitor.")
+ forge_traitor_objectives(character.mind)
+ equip_traitor(character)
+ traitors += character.mind
+ character << "\red You are the traitor."
+ character.mind.special_role = "traitor"
+ var/obj_count = 1
+ character << "\blue Your current objectives:"
+ for(var/datum/objective/objective in character.mind.objectives)
+ character << "Objective #[obj_count]: [objective.explanation_text]"
+ obj_count++
+ //else
+ //message_admins("New traitor roll failed. No new traitor.")
+ //else
+ //message_admins("Late Joiner does not have Be Syndicate")
+
+
+
diff --git a/code/game/gamemodes/revolution/rp-revolution.dm b/code/game/gamemodes/revolution/rp-revolution.dm
new file mode 100644
index 00000000000..ce0ade235c9
--- /dev/null
+++ b/code/game/gamemodes/revolution/rp-revolution.dm
@@ -0,0 +1,349 @@
+// To add a rev to the list of revolutionaries, make sure it's rev (with if(ticker.mode.name == "revolution)),
+// then call ticker.mode:add_revolutionary(_THE_PLAYERS_MIND_)
+// nothing else needs to be done, as that proc will check if they are a valid target.
+// Just make sure the converter is a head before you call it!
+// To remove a rev (from brainwashing or w/e), call ticker.mode:remove_revolutionary(_THE_PLAYERS_MIND_),
+// this will also check they're not a head, so it can just be called freely
+// If the rev icons start going wrong for some reason, ticker.mode:update_all_rev_icons() can be called to correct them.
+// If the game somtimes isn't registering a win properly, then ticker.mode.check_win() isn't being called somewhere.
+#define RPREV_REQUIRE_REVS_ALIVE 0
+#define RPREV_REQUIRE_HEADS_ALIVE 0
+
+/datum/game_mode/rp_revolution
+ name = "rp-revolution"
+ config_tag = "rp-revolution"
+
+ var/finished = 0
+ 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/all_brigged = 0
+ var/brigged_time = 0
+
+ uplink_welcome = "Syndicate Uplink Console:"
+ uplink_uses = 10
+
+
+/datum/game_mode/rp_revolution/announce()
+ world << "The current game mode is - Revolution RP!"
+// world << "Some crewmembers are attempting to start a revolution!
\nRevolutionaries - Kill the Captain, HoP, and HoS. Convert other crewmembers (excluding the Captain, HoP, HoS, and security officers) to your cause. Protect your leaders.
\nPersonnel - Protect the Captain, HoP, and HoR. Kill the leaders of the revolution, and brainwash the other revolutionaries (by beating them in the head)."
+
+/datum/game_mode/rp_revolution/send_intercept()
+ var/intercepttext = "Cent. Com. Update Requested staus information:
"
+ intercepttext += " Cent. Com has recently been contacted by the following syndicate affiliated organisations in your area, please investigate any information you may have:"
+
+ var/list/possible_modes = list()
+ possible_modes.Add("revolution", "wizard", "nuke", "traitor", "malf")
+ possible_modes -= "nuke"
+ var/number = pick(2, 3)
+ var/i = 0
+ for(i = 0, i < number, i++)
+ possible_modes.Remove(pick(possible_modes))
+ possible_modes.Insert(rand(possible_modes.len), "nuke")
+
+ var/datum/intercept_text/i_text = new /datum/intercept_text
+ for(var/A in possible_modes)
+ intercepttext += i_text.build(A, pick(head_revolutionaries))
+
+ for (var/obj/machinery/computer/communications/comm in world)
+ if (!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept)
+ var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc )
+ intercept.name = "paper- 'Cent. Com. Status Summary'"
+ intercept.info = intercepttext
+
+ comm.messagetitle.Add("Cent. Com. Status Summary")
+ comm.messagetext.Add(intercepttext)
+
+ command_alert("Summary downloaded and printed out at all communications consoles.", "Enemy communication intercept. Security Level Elevated.")
+
+/datum/game_mode/rp_revolution/post_setup()
+
+ var/list/revs_possible = list()
+ revs_possible = get_possible_revolutionaries()
+ var/list/heads = list()
+ heads = get_living_heads()
+ var/rev_number = 0
+
+ if(!revs_possible || !heads)
+ world << " \red Not enough players for RP revolution game mode. Restarting world in 5 seconds."
+ sleep(50)
+ world.Reboot()
+ return
+
+ if(revs_possible.len >= 3)
+ rev_number = 3
+ else
+ rev_number = revs_possible.len
+
+ while(rev_number > 0)
+ head_revolutionaries += pick(revs_possible - head_revolutionaries)
+ rev_number--
+
+ for(var/datum/mind/rev_mind in head_revolutionaries)
+ for(var/datum/mind/head_mind in heads)
+ var/datum/objective/capture/rev_obj = new
+ rev_obj.owner = rev_mind
+ rev_obj.find_target_by_role(head_mind.assigned_role)
+ rev_mind.objectives += rev_obj
+ equip_revolutionary(rev_mind.current)
+ rev_mind.current.verbs += /mob/living/carbon/human/proc/RevConvert
+ update_rev_icons_added(rev_mind)
+
+ for(var/datum/mind/rev_mind in head_revolutionaries)
+ var/obj_count = 1
+ rev_mind.current << "\blue You are a member of the revolutionaries' leadership!"
+ for(var/datum/objective/objective in rev_mind.objectives)
+ rev_mind.current << "Objective #[obj_count]: [objective.explanation_text]"
+ obj_count++
+
+ spawn (rand(waittime_l, waittime_h))
+ send_intercept()
+
+/datum/game_mode/rp_revolution/send_intercept()
+ var/intercepttext = "Cent. Com. Update Requested staus information:
"
+ intercepttext += " Cent. Com has recently been contacted by the following syndicate affiliated organisations in your area, please investigate any information you may have:"
+
+ var/list/possible_modes = list()
+ possible_modes.Add("revolution", "wizard", "nuke", "traitor", "malf")
+ possible_modes -= "[ticker.mode]"
+ var/number = pick(2, 3)
+ var/i = 0
+ for(i = 0, i < number, i++)
+ possible_modes.Remove(pick(possible_modes))
+ possible_modes.Insert(rand(possible_modes.len), "[ticker.mode]")
+
+ var/datum/intercept_text/i_text = new /datum/intercept_text
+ for(var/A in possible_modes)
+ intercepttext += i_text.build(A, pick(head_revolutionaries))
+
+ for (var/obj/machinery/computer/communications/comm in world)
+ if (!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept)
+ var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc )
+ intercept.name = "paper- 'Cent. Com. Status Summary'"
+ intercept.info = intercepttext
+
+ comm.messagetitle.Add("Cent. Com. Status Summary")
+ comm.messagetext.Add(intercepttext)
+
+ command_alert("Summary downloaded and printed out at all communications consoles.", "Enemy communication intercept. Security Level Elevated.")
+
+ spawn(54000)
+ command_alert("Summary downloaded and printed out at all communications consoles.", "The revolution leaders have been determined.")
+ intercepttext = "Cent. Com. Update Requested status information:
"
+ intercepttext += "We have determined the revolution leaders to be:"
+ for(var/datum/mind/revmind in head_revolutionaries)
+ intercepttext += "
[revmind.current.real_name]"
+ intercepttext += "
Please arrest them at once."
+ for (var/obj/machinery/computer/communications/comm in world)
+ if (!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept)
+ var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc )
+ intercept.name = "paper- 'Cent. Com. Status Summary'"
+ intercept.info = intercepttext
+
+ comm.messagetitle.Add("Cent. Com. Status Summary")
+ comm.messagetext.Add(intercepttext)
+ spawn(12000)
+ command_alert("Repeating the previous message over intercoms due to urgency. The station has enemy operatives onboard by the names of [reveal_rev_heads()], please arrest them at once.", "The revolution leaders have been determined.")
+
+
+/datum/game_mode/rp_revolution/proc/reveal_rev_heads()
+ . = ""
+ for(var/i = 1, i <= head_revolutionaries.len,i++)
+ var/datum/mind/revmind = head_revolutionaries[i]
+ if(i < head_revolutionaries.len)
+ . += "[revmind.current.real_name],"
+ else
+ . += "and [revmind.current.real_name]"
+
+///datum/game_mode/rp_revolution/proc/equip_revolutionary(mob/living/carbon/human/rev_mob)
+// if(!istype(rev_mob))
+// return
+
+// spawn (100)
+// if (rev_mob.r_store)
+// rev_mob.equip_if_possible(new /obj/item/weapon/paper/communist_manifesto(rev_mob), rev_mob.slot_l_store)
+// if (rev_mob.l_store)
+// rev_mob.equip_if_possible(new /obj/item/weapon/paper/communist_manifesto(rev_mob), rev_mob.slot_r_store)
+
+
+/datum/game_mode/rp_revolution/check_win()
+ if(check_rev_victory())
+ finished = 1
+ else if(check_heads_victory())
+ finished = 2
+ return
+
+/datum/game_mode/rp_revolution/check_finished()
+ if(finished != 0)
+ return 1
+ else
+ return 0
+
+/datum/game_mode/rp_revolution/proc/get_possible_revolutionaries()
+ var/list/candidates = list()
+
+ for(var/mob/living/carbon/human/player in world)
+ if(player.client)
+ if(player.be_syndicate)
+ candidates += player.mind
+
+ if(candidates.len < 1)
+ for(var/mob/living/carbon/human/player in world)
+ if(player.client)
+ candidates += player.mind
+
+ var/list/uncons = get_unconvertables()
+ for(var/datum/mind/mind in uncons)
+ candidates -= mind
+
+ if(candidates.len < 1)
+ return null
+ else
+ return candidates
+
+/datum/game_mode/rp_revolution/proc/get_unconvertables()
+ var/list/ucs = list()
+ for(var/mob/living/carbon/human/player in world)
+ if(player.mind)
+ var/role = player.mind.assigned_role
+ if(role in list("Captain", "Head of Security", "Head of Personnel", "Chief Engineer", "Research Director", "Security Officer", "Forensic Technician", "AI"))
+ ucs += player.mind
+
+ return ucs
+
+/datum/game_mode/rp_revolution/proc/check_rev_victory()
+ for(var/datum/mind/rev_mind in head_revolutionaries)
+ for(var/datum/objective/objective in rev_mind.objectives)
+ if(!(objective.check_completion()))
+ return 0
+
+ return 1
+
+/datum/game_mode/rp_revolution/proc/check_heads_victory()
+ for(var/datum/mind/rev_mind in head_revolutionaries)
+ if(rev_mind.current.stat != 2)
+ var/turf/revloc = rev_mind.current.loc
+ if(!istype(revloc.loc,/area/security/brig) && !rev_mind.current.handcuffed)
+ return 0
+ else if(RPREV_REQUIRE_REVS_ALIVE) return 0
+ return 1
+
+/datum/game_mode/rp_revolution/declare_completion()
+
+ var/text = ""
+ if(finished == 1)
+ world << "\red The heads of staff were relieved of their posts! The revolutionaries win!"
+ else if(finished == 2)
+ world << "\red The heads of staff managed to stop the revolution!"
+
+ world << "The head revolutionaries were: "
+ for(var/datum/mind/rev_mind in head_revolutionaries)
+ text = ""
+ if(rev_mind.current)
+ text += "[rev_mind.current.real_name]"
+ if(rev_mind.current.stat == 2)
+ text += " (Dead)"
+ else
+ text += " (Survived!)"
+ else
+ text += "[rev_mind.key] (character destroyed)"
+
+ world << text
+
+ text = ""
+ world << "The converted revolutionaries were: "
+ for(var/datum/mind/rev_nh_mind in revolutionaries)
+ if(rev_nh_mind.current)
+ text += "[rev_nh_mind.current.real_name]"
+ if(rev_nh_mind.current.stat == 2)
+ text += " (Dead)"
+ else
+ text += " (Survived!)"
+ else
+ text += "[rev_nh_mind.key] (character destroyed)"
+ text += ", "
+
+ world << text
+
+ world << "The heads of staff were: "
+ var/list/heads = list()
+ heads = get_all_heads()
+ for(var/datum/mind/head_mind in heads)
+ text = ""
+ if(head_mind.current)
+ text += "[head_mind.current.real_name]"
+ if(head_mind.current.stat == 2)
+ text += " (Dead)"
+ else
+ text += " (Survived!)"
+ else
+ text += "[head_mind.key] (character destroyed)"
+
+ world << text
+ return 1
+
+
+/*obj/item/weapon/paper/communist_manifesto
+ name = "Communist Manifesto"
+ icon = 'books.dmi'
+ icon_state = "redcommunist"
+ info = "Supporters of the Revolution:
"
+ attack(mob/living/carbon/M as mob, mob/user as mob)
+ if(user.mind in ticker.mode:head_revolutionaries)
+ if(RevConvert(M,user))
+ for(var/mob/O in viewers(user, null))
+ O.show_message(text("\red [] converts [] with the Communist Manifesto!", user, M))
+ info += "[M.real_name]
"
+ else
+ for(var/mob/O in viewers(user, null))
+ O.show_message(text("\red [] fails to convert [] with the Communist Manifesto!", user, M))
+ else
+ usr << "\red You are completely confounded as to the operation of this tome."
+ return
+
+proc/RevConvert(mob/living/carbon/M,mob/user)
+ if(!istype(M)) return 0
+ if((M.mind in ticker.mode:head_revolutionaries) || (M.mind in ticker.mode:revolutionaries))
+ user << "\red [M] is already a revolutionary!"
+ return 0
+ else if(M.mind in ticker.mode:get_unconvertables())
+ user << "\red [M] cannot be a revolutionary!"
+ return 0
+ else
+ if(world.time < M.mind.rev_cooldown)
+ user << "\red Wait five seconds before reconversion attempt."
+ return 0
+ user << "\red Attempting to convert [M]..."
+ var/choice = alert(M,"Asked by [user]: Do you want to join the revolution?","Align Thyself with the Revolution!","No!","Yes!")
+ if(choice == "Yes!")
+ ticker.mode:add_revolutionary(M.mind)
+ user << "\blue [M] joins the revolution!"
+ . = 1
+ else if(choice == "No!")
+ user << "\red [M] does not support the revolution!"
+ . = 0
+ M.mind.rev_cooldown = world.time+50*/
+
+mob/living/carbon/human/proc
+ RevConvert(mob/M as mob in oview(src))
+ set name = "Rev-Convert"
+ if(((src.mind in ticker.mode:head_revolutionaries) || (src.mind in ticker.mode:revolutionaries)))
+ if((M.mind in ticker.mode:head_revolutionaries) || (M.mind in ticker.mode:revolutionaries))
+ src << "\red [M] is already be a revolutionary!"
+ else if(src.mind in ticker.mode:get_unconvertables())
+ src << "\red [M] cannot be a revolutionary!"
+ else
+ if(world.time < M.mind.rev_cooldown)
+ src << "\red Wait five seconds before reconversion attempt."
+ return
+ src << "\red Attempting to convert [M]..."
+ log_admin("[src]([src.ckey]) attempted to convert [M].")
+ message_admins("\red [src]([src.ckey]) attempted to convert [M].")
+ var/choice = alert(M,"Asked by [src]: Do you want to join the revolution?","Align Thyself with the Revolution!","No!","Yes!")
+ if(choice == "Yes!")
+ ticker.mode:add_revolutionary(M.mind)
+ M << "\blue You join the revolution!"
+ src << "\blue [M] joins the revolution!"
+ else if(choice == "No!")
+ M << "\red You reject this traitorous cause!"
+ src << "\red [M] does not support the revolution!"
+ M.mind.rev_cooldown = world.time+50
\ No newline at end of file