diff --git a/baystation12.dme b/baystation12.dme
index 6e27d465476..d2b7b61fcf4 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -417,6 +417,7 @@
#include "code\game\gamemodes\intercept_report.dm"
#include "code\game\gamemodes\objective.dm"
#include "code\game\gamemodes\setupgame.dm"
+#include "code\game\gamemodes\autotraitor\autotraitor.dm"
#include "code\game\gamemodes\blob\blob.dm"
#include "code\game\gamemodes\blob\blob_finish.dm"
#include "code\game\gamemodes\blob\blob_report.dm"
@@ -454,6 +455,7 @@
#include "code\game\gamemodes\nuclear\nuclearbomb.dm"
#include "code\game\gamemodes\nuclear\pinpointer.dm"
#include "code\game\gamemodes\revolution\revolution.dm"
+#include "code\game\gamemodes\revolution\rp_revolution.dm"
#include "code\game\gamemodes\sandbox\h_sandbox.dm"
#include "code\game\gamemodes\sandbox\sandbox.dm"
#include "code\game\gamemodes\traitor\traitor.dm"
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 113818f6a68..69c68d9c114 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -53,6 +53,8 @@ datum/mind
var/datum/faction/faction //associated faction
var/datum/changeling/changeling //changeling holder
+ var/rev_cooldown = 0
+
New(var/key)
src.key = key
diff --git a/code/datums/organs/organ_external.dm b/code/datums/organs/organ_external.dm
index 00b9a54a471..48f42ba16b2 100644
--- a/code/datums/organs/organ_external.dm
+++ b/code/datums/organs/organ_external.dm
@@ -105,8 +105,8 @@
possible_points += children
if(forbidden_limbs.len)
possible_points -= forbidden_limbs
- if(!possible_points.len)
- message_admins("Oh god WHAT! [owner]'s [src] was unable to find an organ to pass overdamage too!")
+ // if(!possible_points.len)
+ // message_admins("Oh god WHAT! [owner]'s [src] was unable to find an organ to pass overdamage to!")
else
var/datum/organ/external/target = pick(possible_points)
if(brute)
diff --git a/code/game/gamemodes/autotraitor/autotraitor.dm b/code/game/gamemodes/autotraitor/autotraitor.dm
index 930fe363f8c..e9c7b7f794d 100644
--- a/code/game/gamemodes/autotraitor/autotraitor.dm
+++ b/code/game/gamemodes/autotraitor/autotraitor.dm
@@ -7,12 +7,17 @@
config_tag = "Extend-A-Traitormongous"
var/list/possible_traitors
+ var/num_players = 0
/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."
+ world << "Game mode is AutoTraitor. Traitors will be added to the round automagically as needed.
Expect bugs."
/datum/game_mode/traitor/autotraitor/pre_setup()
+
+ if(config.protect_roles_from_antagonist)
+ restricted_jobs += protected_jobs
+
possible_traitors = get_players_for_role(BE_TRAITOR)
for(var/datum/mind/player in possible_traitors)
@@ -134,33 +139,6 @@
//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()
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 5240f2b3674..0f33bddb993 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -324,6 +324,8 @@ Whitespace:Seperator;
// Less if there are not enough valid players in the game entirely to make recommended_enemies.
+/datum/game_mode/proc/latespawn(var/mob)
+
/datum/game_mode/proc/check_player_role_pref(var/role, var/mob/new_player/player)
if(player.preferences.be_special & role)
return 1
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index c35c48bcd94..424c822d5ae 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -86,6 +86,39 @@ datum/objective/mutiny
return 0
return 1
+datum/objective/mutiny/rp
+ find_target()
+ ..()
+ if(target && target.current)
+ explanation_text = "Assassinate, capture or convert [target.current.real_name], the [target.assigned_role]."
+ else
+ explanation_text = "Free Objective"
+ return target
+
+
+ find_target_by_role(role, role_type=0)
+ ..(role, role_type)
+ if(target && target.current)
+ explanation_text = "Assassinate, capture or convert [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role]."
+ else
+ explanation_text = "Free Objective"
+ return target
+
+ // less violent rev objectives
+ check_completion()
+ if(target && target.current)
+ if(target.current.stat == DEAD || target.current.handcuffed || !ishuman(target.current))
+ return 1
+ // Check if they're converted
+ if(istype(ticker.mode, /datum/game_mode/revolution))
+ if(target in ticker.mode:head_revolutionaries)
+ return 1
+ var/turf/T = get_turf(target.current)
+ if(T && (T.z != 1)) //If they leave the station they count as dead for this
+ return 2
+ return 0
+ return 1
+
datum/objective/debrain//I want braaaainssss
find_target()
diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm
index fe03323c86b..a210d856cde 100644
--- a/code/game/gamemodes/revolution/revolution.dm
+++ b/code/game/gamemodes/revolution/revolution.dm
@@ -25,7 +25,7 @@
var/finished = 0
var/checkwin_counter = 0
- var/const/max_headrevs = 3
+ var/max_headrevs = 3
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)
///////////////////////////
diff --git a/code/game/gamemodes/revolution/rp-revolution.dm b/code/game/gamemodes/revolution/rp-revolution.dm
index 1c8d2367eeb..7456e73403b 100644
--- a/code/game/gamemodes/revolution/rp-revolution.dm
+++ b/code/game/gamemodes/revolution/rp-revolution.dm
@@ -280,46 +280,6 @@
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))
diff --git a/code/game/gamemodes/revolution/rp_revolution.dm b/code/game/gamemodes/revolution/rp_revolution.dm
new file mode 100644
index 00000000000..4f02f87b74e
--- /dev/null
+++ b/code/game/gamemodes/revolution/rp_revolution.dm
@@ -0,0 +1,192 @@
+// BS12's less violent revolution mode
+
+/datum/game_mode/revolution/rp_revolution
+ name = "rp-revolution"
+ config_tag = "rp-revolution"
+ required_players = 12
+ required_enemies = 3
+ recommended_enemies = 3
+
+ var/list/heads = list()
+ var/tried_to_add_revheads = 0
+
+///////////////////////////////////////////////////////////////////////////////
+//Gets the round setup, cancelling if there's not enough players at the start//
+///////////////////////////////////////////////////////////////////////////////
+/datum/game_mode/revolution/rp_revolution/pre_setup()
+
+ if(config.protect_roles_from_antagonist)
+ restricted_jobs += protected_jobs
+
+ var/num_players = num_players()
+ max_headrevs = max(num_players / 4, 3)
+ recommended_enemies = max_headrevs
+
+ var/list/datum/mind/possible_headrevs = get_players_for_role(BE_REV)
+
+ var/head_check = 0
+ for(var/mob/new_player/player in player_list)
+ if(player.mind.assigned_role in command_positions)
+ head_check = 1
+ break
+
+ for(var/datum/mind/player in possible_headrevs)
+ for(var/job in restricted_jobs)//Removing heads and such from the list
+ if(player.assigned_role == job)
+ possible_headrevs -= player
+
+ for (var/i=1 to max_headrevs)
+ if (possible_headrevs.len==0)
+ break
+ var/datum/mind/lenin = pick(possible_headrevs)
+ possible_headrevs -= lenin
+ head_revolutionaries += lenin
+
+ if((head_revolutionaries.len==0)||(!head_check))
+ return 0
+
+ return 1
+
+
+/datum/game_mode/revolution/rp_revolution/post_setup()
+ heads = get_living_heads()
+
+ for(var/datum/mind/rev_mind in head_revolutionaries)
+ for(var/datum/mind/head_mind in heads)
+ var/datum/objective/mutiny/rp/rev_obj = new
+ rev_obj.owner = rev_mind
+ rev_obj.target = head_mind
+ rev_obj.explanation_text = "Assassinate or capture [head_mind.name], the [head_mind.assigned_role]."
+ rev_mind.objectives += rev_obj
+
+ update_rev_icons_added(rev_mind)
+
+ for(var/datum/mind/rev_mind in head_revolutionaries)
+ greet_revolutionary(rev_mind)
+ rev_mind.current.verbs += /mob/living/carbon/human/proc/RevConvert
+ modePlayer += head_revolutionaries
+ spawn (rand(waittime_l, waittime_h))
+ send_intercept()
+ ..()
+
+/datum/game_mode/revolution/rp_revolution/greet_revolutionary(var/datum/mind/rev_mind, var/you_are=1)
+ var/obj_count = 1
+ if (you_are)
+ 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]"
+ rev_mind.special_role = "Head Revolutionary"
+ obj_count++
+
+///////////////////////////////////////////////////
+//Deals with converting players to the revolution//
+///////////////////////////////////////////////////
+/datum/game_mode/revolution/rp_revolution/add_revolutionary(datum/mind/rev_mind)
+ // overwrite this func to make it so even heads can be converted
+ var/mob/living/carbon/human/H = rev_mind.current//Check to see if the potential rev is implanted
+ if(!is_convertible(H))
+ return 0
+ if((rev_mind in revolutionaries) || (rev_mind in head_revolutionaries))
+ return 0
+ revolutionaries += rev_mind
+ rev_mind.current << "\red You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill, capture or convert the heads to win the revolution!"
+ rev_mind.special_role = "Revolutionary"
+ update_rev_icons_added(rev_mind)
+ return 1
+
+/////////////////////////////
+//Checks for a head victory//
+/////////////////////////////
+/datum/game_mode/revolution/rp_revolution/check_heads_victory()
+ for(var/datum/mind/rev_mind in head_revolutionaries)
+ var/turf/T = get_turf(rev_mind.current)
+ if(rev_mind.current.stat != 2)
+ // TODO: add a similar check that also checks whether they're without ID in the brig..
+ // probably wanna export this stuff into a separate function for use by both
+ // revs and heads
+ if(!rev_mind.current.handcuffed && T && T.z == 1)
+ return 0
+ return 1
+
+//////////////////////////////////////////////////////////////////////
+//Announces the end of the game with all relavent information stated//
+//////////////////////////////////////////////////////////////////////
+/datum/game_mode/revolution/rp_revolution/declare_completion()
+ if(finished == 1)
+ feedback_set_details("round_end_result","win - heads overthrown")
+ world << "\red The heads of staff were overthrown! The revolutionaries win!"
+ else if(finished == 2)
+ feedback_set_details("round_end_result","loss - revolution stopped")
+ world << "\red The heads of staff managed to stop the revolution!"
+ ..()
+ return 1
+
+/datum/game_mode/revolution/proc/is_convertible(mob/M)
+ for(var/obj/item/weapon/implant/loyalty/L in M)//Checking that there is a loyalty implant in the contents
+ if(L.imp_in == M)//Checking that it's actually implanted
+ return 0
+
+ return 1
+
+/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(ticker.mode:is_convertible(M))
+ src << "\red [M] is implanted with a loyalty implant - Remove it first!"
+ 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
+
+/datum/game_mode/revolution/rp_revolution/process()
+ // only perform rev checks once in a while
+ if(tried_to_add_revheads < world.time)
+ tried_to_add_revheads = world.time+50
+ for(var/datum/mind/rev_mind in head_revolutionaries)
+ var/active_revs = 0
+ if(rev_mind.current.client && rev_mind.current.client.inactivity <= 10*60*20) // 20 minutes inactivity are OK
+ active_revs++
+
+ if(active_revs == 0)
+ log_admin("There are zero active head revolutionists, trying to add some..")
+ message_admins("There are zero active head revolutionists, trying to add some..")
+ var/added_heads = 0
+ for(var/mob/living/carbon/human/H in world) if(H.client && H.mind && H.client.inactivity <= 10*60*20 && H.mind in revolutionaries)
+ head_revolutionaries += H.mind
+ for(var/datum/mind/head_mind in heads)
+ var/datum/objective/mutiny/rp/rev_obj = new
+ rev_obj.owner = H.mind
+ rev_obj.target = head_mind
+ rev_obj.explanation_text = "Assassinate or capture [head_mind.name], the [head_mind.assigned_role]."
+ H.mind.objectives += rev_obj
+
+ update_rev_icons_added(H.mind)
+ H.verbs += /mob/living/carbon/human/proc/RevConvert
+
+ H << "\red Congratulations, yer heads of revolution are all gone now, so yer earned yourself a promotion."
+ added_heads = 1
+ break
+
+ if(added_heads)
+ log_admin("Managed to add new heads of revolution.")
+ message_admins("Managed to add new heads of revolution.")
+ else
+ log_admin("Unable to add new heads of revolution.")
+ message_admins("Unable to add new heads of revolution.")
+ tried_to_add_revheads = world.time + 6000 // wait 10 minutes
+
+ return ..()
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm
index dfd37287e69..870c190e131 100644
--- a/code/game/objects/items/weapons/storage/backpack.dm
+++ b/code/game/objects/items/weapons/storage/backpack.dm
@@ -42,7 +42,7 @@
..()
return
- attackby(obj/item/weapon/W as obj, mob/user as mob)
+/* attackby(obj/item/weapon/W as obj, mob/user as mob) //BoH+BoH=Singularity, commented out
if(crit_fail)
user << "\red The Bluespace generator isn't working."
return
@@ -57,7 +57,7 @@
del(src)
return
..()
-
+*/
proc/failcheck(mob/user as mob)
if (prob(src.reliability)) return 1 //No failure
if (prob(src.reliability))
diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm
index 3cf36ab5e36..ce43e6e1130 100644
--- a/code/modules/client/client defines.dm
+++ b/code/modules/client/client defines.dm
@@ -25,6 +25,7 @@
var/played = 0
var/be_alien = 0 //Check if that guy wants to be an alien
var/be_pai = 1 //Consider client when searching for players to recruit as a pAI
+ var/be_syndicate = 1 //Consider client for late-game autotraitor
var/activeslot = 1 //Default active slot!
var/STFU_ghosts //80+ people rounds are fun to admin when text flies faster than airport security
var/STFU_radio //80+ people rounds are fun to admin when text flies faster than airport security
diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm
index 97b123825b1..4759f8cdc71 100644
--- a/code/modules/mob/new_player/new_player.dm
+++ b/code/modules/mob/new_player/new_player.dm
@@ -344,6 +344,11 @@
character.loc = pick(latejoin)
character.lastarea = get_area(loc)
+ if(character.client)
+ character.client.be_syndicate = preferences.be_special
+
+ ticker.mode.latespawn(character)
+
if(character.mind.assigned_role != "Cyborg")
data_core.manifest_inject(character)
ticker.minds += character.mind//Cyborgs and AIs handle this in the transform proc. //TODO!!!!! ~Carn
diff --git a/code/modules/mob/new_player/preferences.dm b/code/modules/mob/new_player/preferences.dm
index d226be17772..b02c49ba8be 100644
--- a/code/modules/mob/new_player/preferences.dm
+++ b/code/modules/mob/new_player/preferences.dm
@@ -1128,6 +1128,7 @@ datum/preferences
C.midis = src.midis
C.be_alien = be_special & BE_ALIEN
C.be_pai = be_special & BE_PAI
+ C.be_syndicate = be_special & BE_TRAITOR
if(isnull(src.ghost_ears)) src.ghost_ears = 1 //There were problems where the default was null before someone saved their profile.
C.ghost_ears = src.ghost_ears
C.ghost_sight = src.ghost_sight
diff --git a/config/admins.txt b/config/admins.txt
index 8e13eba12da..c2b5bf032eb 100644
--- a/config/admins.txt
+++ b/config/admins.txt
@@ -1,5 +1,6 @@
abi79 - Game Master
arcalane - Game Admin
+asanadas - Game Admin
bobbehluvspropane - Game Admin
cacophony - Game Admin
cajoes - Game Admin
diff --git a/config/moderators.txt b/config/moderators.txt
index 7a1254afc2f..50ff65102b4 100644
--- a/config/moderators.txt
+++ b/config/moderators.txt
@@ -1,6 +1,5 @@
; just add the ckey (lowercase) of every moderator on a separate line
; lines starting with ; are comments and will be ignored
-asanadas
botanistpower
bowlsoldier
cubejackal