diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm
index c8407907757..c7726f9f328 100644
--- a/code/__HELPERS/roundend.dm
+++ b/code/__HELPERS/roundend.dm
@@ -719,9 +719,9 @@
var/count = 1
for(var/datum/objective/objective in objectives)
if(objective.check_completion())
- objective_parts += "Objective #[count]: [objective.explanation_text] Success!"
+ objective_parts += "[objective.objective_name] #[count]: [objective.explanation_text] Success!"
else
- objective_parts += "Objective #[count]: [objective.explanation_text] Fail."
+ objective_parts += "[objective.objective_name] #[count]: [objective.explanation_text] Fail."
count++
return objective_parts.Join("
")
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index cda5668fa40..969cc0af50c 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -659,9 +659,8 @@
/datum/mind/proc/announce_objectives()
var/obj_count = 1
to_chat(current, "Your current objectives:")
- for(var/objective in get_all_objectives())
- var/datum/objective/O = objective
- to_chat(current, "Objective #[obj_count]: [O.explanation_text]")
+ for(var/datum/objective/objective as anything in get_all_objectives())
+ to_chat(current, "[objective.objective_name] #[obj_count]: [objective.explanation_text]")
obj_count++
/datum/mind/proc/find_syndicate_uplink()
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index 0a52636cf1e..45c16de0608 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -5,6 +5,8 @@ GLOBAL_LIST(admin_objective_list) //Prefilled admin assignable objective list
var/datum/team/team //An alternative to 'owner': a team. Use this when writing new code.
var/name = "generic objective" //Name for admin prompts
var/explanation_text = "Nothing" //What that person is supposed to do.
+ ///name used in printing this objective (Objective #1)
+ var/objective_name = "Objective"
var/team_explanation_text //For when there are multiple owners.
var/datum/mind/target = null //If they are focused on a particular person.
var/target_amount = 0 //If they are focused on a particular number. Steal objectives have their own counter.
@@ -515,6 +517,19 @@ GLOBAL_LIST(admin_objective_list) //Prefilled admin assignable objective list
return FALSE
return TRUE
+/datum/objective/exile
+ name = "exile"
+ explanation_text = "Stay alive off station. Do not go to CentCom."
+
+/datum/objective/exile/check_completion()
+ var/list/owners = get_owners()
+ for(var/datum/mind/mind as anything in owners)
+ if(!considered_alive(mind))
+ return FALSE
+ if(SSmapping.level_has_any_trait(mind.current.z, list(ZTRAIT_STATION, ZTRAIT_CENTCOM))) //went to centcom or ended round on station
+ return FALSE
+ return TRUE
+
/datum/objective/martyr
name = "martyr"
explanation_text = "Die a glorious death."
diff --git a/code/modules/antagonists/revolution/enemy_of_the_revolution.dm b/code/modules/antagonists/revolution/enemy_of_the_revolution.dm
new file mode 100644
index 00000000000..ea10f577fe1
--- /dev/null
+++ b/code/modules/antagonists/revolution/enemy_of_the_revolution.dm
@@ -0,0 +1,25 @@
+
+/**
+ * When the revolution wins, any remaining heads and security become Enemies of the Revolution.
+ * Previously being nonantagonists, they only have one simple objective: survive!
+ */
+/datum/antagonist/enemy_of_the_revolution
+ name = "Enemy of the Revolution"
+ show_in_antagpanel = FALSE
+
+/datum/antagonist/enemy_of_the_revolution/proc/forge_objectives()
+ var/datum/objective/survive/survive = new
+ survive.owner = owner
+ survive.explanation_text = "The station has been overrun by revolutionaries, stay alive until the end."
+ objectives += survive
+
+/datum/antagonist/enemy_of_the_revolution/on_gain()
+ //the state version of this antag has to sleep a tick, this doesn't because it's not replacing an old antag datum.
+ owner.special_role = "revolution enemy"
+ forge_objectives()
+ . = ..()
+
+/datum/antagonist/enemy_of_the_revolution/greet()
+ to_chat(owner, "The station is lost.")
+ to_chat(owner, "As a surviving loyalist of the previous system, Your days are numbered.")
+ owner.announce_objectives()
diff --git a/code/modules/antagonists/revolution/enemy_of_the_state.dm b/code/modules/antagonists/revolution/enemy_of_the_state.dm
new file mode 100644
index 00000000000..4c99940a8f4
--- /dev/null
+++ b/code/modules/antagonists/revolution/enemy_of_the_state.dm
@@ -0,0 +1,66 @@
+
+/**
+ * When the station wins, any remaining living headrevs become Enemies of the State, a small solo antagonist.
+ * They either have the choice to fuck off and do their own thing, or try and regain their honor with a hijack.
+ */
+/datum/antagonist/enemy_of_the_state
+ name = "Enemy of the State"
+ show_in_antagpanel = FALSE
+ show_name_in_check_antagonists = TRUE
+ hijack_speed = 2 //not like they have much to do
+
+/datum/antagonist/enemy_of_the_state/proc/forge_objectives()
+
+ var/datum/objective/exile/exile_choice = new
+ exile_choice.owner = owner
+ exile_choice.objective_name = "Choice"
+ objectives += exile_choice
+
+ var/datum/objective/hijack/hijack_choice = new
+ hijack_choice.owner = owner
+ hijack_choice.objective_name = "Choice"
+ objectives += hijack_choice
+
+/datum/antagonist/enemy_of_the_state/on_gain()
+ owner.special_role = "exiled headrev"
+ forge_objectives()
+ . = ..()
+
+/datum/antagonist/enemy_of_the_state/greet()
+ to_chat(owner, "The revolution is dead.")
+ to_chat(owner, "You're an enemy of the state to Nanotrasen. You're a loose end to the Syndicate.")
+ to_chat(owner, "It's time to live out your days as an exile... or go out in one last big bang.")
+ owner.announce_objectives()
+
+/datum/antagonist/enemy_of_the_state/roundend_report()
+ var/list/report = list()
+
+ if(!owner)
+ CRASH("Antagonist datum without owner")
+
+ report += printplayer(owner)
+
+ //needs to complete only one objective, not all
+
+ var/option_chosen = FALSE
+ var/badass = FALSE
+ if(objectives.len)
+ report += printobjectives(objectives)
+ for(var/datum/objective/objective in objectives)
+ if(objective.check_completion())
+ option_chosen = TRUE
+ if(istype(objective, /datum/objective/hijack))
+ badass = TRUE
+ break
+
+ if(objectives.len == 0 || option_chosen)
+ if(badass)
+ report += "Major [name] Victory"
+ report += "[name] chose the badass option, and hijacked the shuttle!"
+ else
+ report += "Minor [name] Victory"
+ report += "[name] has survived as an exile!"
+ else
+ report += "The [name] has failed!"
+
+ return report.Join("
")
diff --git a/code/modules/antagonists/revolution/revolution.dm b/code/modules/antagonists/revolution/revolution.dm
index da7bd22f8d7..1de50eb44c9 100644
--- a/code/modules/antagonists/revolution/revolution.dm
+++ b/code/modules/antagonists/revolution/revolution.dm
@@ -12,6 +12,8 @@
antag_hud_type = ANTAG_HUD_REV
antag_hud_name = "rev"
var/datum/team/revolution/rev_team
+ ///when this antagonist is being de-antagged, this is why
+ var/deconversion_reason
/// What message should the player receive when they are being demoted, and the revolution has won?
var/victory_message = "The revolution has overpowered the command staff! Viva la revolution! Execute any head of staff and security should you find them alive."
@@ -229,9 +231,8 @@
to_chat(owner, "The frame's firmware detects and deletes your neural reprogramming! You remember nothing but the name of the one who flashed you.")
/datum/antagonist/rev/head/farewell()
- if (announce_victorious())
+ if (announce_victorious() || deconversion_reason == DECONVERTER_STATION_WIN)
return
-
if((ishuman(owner.current)))
if(owner.current.stat != DEAD)
owner.current.visible_message("[owner.current] looks like [owner.current.p_theyve()] just remembered [owner.current.p_their()] real allegiance!", null, null, null, owner.current)
@@ -251,12 +252,18 @@
if(iscarbon(owner.current) && deconverter != DECONVERTER_REVS_WIN)
var/mob/living/carbon/C = owner.current
C.Unconscious(100)
+ deconversion_reason = deconverter
owner.remove_antag_datum(type)
-/datum/antagonist/rev/head/remove_revolutionary(borged,deconverter)
+/datum/antagonist/rev/head/remove_revolutionary(borged, deconverter)
+ var/re_antag = FALSE
+ var/datum/mind/old_owner = owner //owner gets nulled when rev antag removed
if(borged || deconverter == DECONVERTER_STATION_WIN || deconverter == DECONVERTER_REVS_WIN)
+ if(owner.current.stat != DEAD && deconverter == DECONVERTER_STATION_WIN)
+ re_antag = TRUE
. = ..()
-
+ if(re_antag)
+ old_owner.add_antag_datum(/datum/antagonist/enemy_of_the_state) //needs to be post ..() so old antag status is cleaned up
/datum/antagonist/rev/head/equip_rev()
var/mob/living/carbon/C = owner.current
if(!ishuman(C))
@@ -280,21 +287,6 @@
S.Insert(C)
to_chat(C, "Your eyes have been implanted with a cybernetic security HUD which will help you keep track of who is mindshield-implanted, and therefore unable to be recruited.")
-/// "Enemy of the Revolutionary", given to heads and security when the revolution wins
-/datum/antagonist/revolution_enemy
- name = "Enemy of the Revolution"
- show_in_antagpanel = FALSE
-
-/datum/antagonist/revolution_enemy/on_gain()
- owner.special_role = "revolution enemy"
-
- var/datum/objective/survive/survive = new /datum/objective/survive
- survive.owner = owner
- survive.explanation_text = "The station has been overrun by revolutionaries, stay alive until the end."
- objectives += survive
-
- return ..()
-
/datum/team/revolution
name = "Revolution"
var/max_headrevs = 3
@@ -429,7 +421,7 @@
var/mob/living/carbon/target_body = mind.current
- mind.add_antag_datum(/datum/antagonist/revolution_enemy)
+ mind.add_antag_datum(/datum/antagonist/enemy_of_the_revolution)
if (!istype(target_body))
continue
diff --git a/tgstation.dme b/tgstation.dme
index 3cc644e6816..1dfcae7b513 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1726,6 +1726,8 @@
#include "code\modules\antagonists\revenant\revenant_antag.dm"
#include "code\modules\antagonists\revenant\revenant_blight.dm"
#include "code\modules\antagonists\revenant\revenant_spawn_event.dm"
+#include "code\modules\antagonists\revolution\enemy_of_the_revolution.dm"
+#include "code\modules\antagonists\revolution\enemy_of_the_state.dm"
#include "code\modules\antagonists\revolution\revolution.dm"
#include "code\modules\antagonists\santa\santa.dm"
#include "code\modules\antagonists\separatist\separatist.dm"