From 491e445a35a3fa44c9ea30ba6920d99176c9b6f7 Mon Sep 17 00:00:00 2001
From: SkyratBot <59378654+SkyratBot@users.noreply.github.com>
Date: Thu, 15 Oct 2020 08:35:34 +0200
Subject: [PATCH] [MIRROR] Ports #10649 from Citadel: An attempt at making
hijack not shit and more about point defence (#1311)
* Ports #10649 from Citadel: An attempt at making hijack not shit and more about point defence (#54146)
So essentially there was discussion already here (https://tgstation13.org/phpBB/viewtopic.php?f=33&t=27620) about how hijack is one of the few objectives on Manuel that you can murderbone with, which is mildly at odds with the intention of the server.
Personally, I think hijack is just straight up terrible regardless of what server you're on. The way it functions is dreadful. Nobody must be aboard the shuttle in any part of the shuttle at all. This means you have people hiding in the walls or hiding in some invisible corner of the shuttle, cucking you of the hijack. For the most part, the only way to actually hijack the shuttle is to render it completely inhospitable or destroying it utterly save for, maybe, one square. The one you are standing on.
It's absurd. So, I knew kev made a pretty honest attempt at reworking hijack. And it works pretty well. It doesn't necessarily solve the problem of hijackers being mandatory mass shooters, but it goes some ways to improving the objective in a more interesting fashion, and allows for the discussion around the objective to be a little more open ended for the sake of the higher roleplay servers without actually detracting from the lower roleplay servers at all. If anything, this should improve the experience of being that gamer to stage a hijacking all the more interesting and about robustness, and less of hide-and-go-seek.
* Ports #10649 from Citadel: An attempt at making hijack not shit and more about point defence
Co-authored-by: necromanceranne <40847847+necromanceranne@users.noreply.github.com>
---
code/__DEFINES/antagonists.dm | 14 +--
code/__HELPERS/text.dm | 15 +++
code/datums/mind.dm | 5 +
code/game/gamemodes/objective.dm | 31 +++--
.../antagonists/_common/antag_datum.dm | 9 +-
code/modules/antagonists/brother/brother.dm | 2 +-
.../antagonists/changeling/changeling.dm | 2 +-
.../eldritch_cult/eldritch_antag.dm | 2 +-
.../eldritch_cult/eldritch_monster_antag.dm | 1 -
code/modules/antagonists/ert/ert.dm | 2 +-
.../antagonists/highlander/highlander.dm | 9 +-
code/modules/antagonists/ninja/ninja.dm | 4 +-
code/modules/antagonists/nukeop/nukeop.dm | 2 +-
code/modules/antagonists/official/official.dm | 2 +-
.../antagonists/traitor/datum_traitor.dm | 2 +-
.../antagonists/wishgranter/wishgranter.dm | 2 +-
code/modules/antagonists/wizard/wizard.dm | 2 +-
code/modules/shuttle/emergency.dm | 111 ++++++++++++++++--
18 files changed, 177 insertions(+), 40 deletions(-)
diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm
index fc59a6b2d94..bf4c44d400f 100644
--- a/code/__DEFINES/antagonists.dm
+++ b/code/__DEFINES/antagonists.dm
@@ -48,13 +48,13 @@
#define DEATHSQUAD "ds"
#define DEATHSQUAD_LEADER "ds_leader"
-//Shuttle hijacking
-/// Does not stop hijacking but itself won't hijack
-#define HIJACK_NEUTRAL 0
-/// Needs to be present for shuttle to be hijacked
-#define HIJACK_HIJACKER 1
-/// Prevents hijacking same way as non-antags
-#define HIJACK_PREVENT 2
+//Shuttle elimination hijacking
+/// Does not stop elimination hijacking but itself won't elimination hijack
+#define ELIMINATION_NEUTRAL 0
+/// Needs to be present for shuttle to be elimination hijacked
+#define ELIMINATION_ENABLED 1
+/// Prevents elimination hijack same way as non-antags
+#define ELIMINATION_PREVENT 2
//Syndicate Contracts
#define CONTRACT_STATUS_INACTIVE 1
diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm
index 0515bdf1e2d..b29ea1d55fc 100644
--- a/code/__HELPERS/text.dm
+++ b/code/__HELPERS/text.dm
@@ -917,3 +917,18 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
var/prefix = prefixes[prefix_index]
return "[coefficient] [prefix][unit]"
+
+/// Slightly expensive proc to scramble a message using equal probabilities of character replacement from a list. DOES NOT SUPPORT HTML!
+/proc/scramble_message_replace_chars(original, replaceprob = 25, list/replacementchars = list("$", "@", "!", "#", "%", "^", "&", "*"), replace_letters_only = FALSE, replace_whitespace = FALSE)
+ var/list/out = list()
+ var/static/list/whitespace = list(" ", "\n", "\t")
+ for(var/i in 1 to length(original))
+ var/char = original[i]
+ if(!replace_whitespace && (char in whitespace))
+ out += char
+ continue
+ if(replace_letters_only && (!ISINRANGE(char, 65, 90) && !ISINRANGE(char, 97, 122)))
+ out += char
+ continue
+ out += prob(replaceprob)? pick(replacementchars) : char
+ return out.Join("")
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 155869dc2ea..76385e63ea5 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -765,6 +765,11 @@
if(G)
G.reenter_corpse()
+/// Sets our can_hijack to the fastest speed our antag datums allow.
+/datum/mind/proc/get_hijack_speed()
+ . = 0
+ for(var/datum/antagonist/A in antag_datums)
+ . = max(., A.hijack_speed())
/datum/mind/proc/has_objective(objective_type)
for(var/datum/antagonist/A in antag_datums)
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index d84fee2c3a6..16ff4cfdfb1 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -350,9 +350,11 @@ GLOBAL_LIST(admin_objective_list) //Prefilled admin assignable objective list
/datum/objective/hijack
name = "hijack"
- explanation_text = "Hijack the shuttle to ensure no loyalist Nanotrasen crew escape alive and out of custody."
- team_explanation_text = "Hijack the shuttle to ensure no loyalist Nanotrasen crew escape alive and out of custody. Leave no team member behind."
+ explanation_text = "Hijack the emergency shuttle by hacking its navigational protocols through the control console (alt click emergency shuttle console)."
+ team_explanation_text = "Hijack the emergency shuttle by hacking its navigational protocols through the control console (alt click emergency shuttle console). Leave no team member behind."
martyr_compatible = FALSE //Technically you won't get both anyway.
+ /// Overrides the hijack speed of any antagonist datum it is on ONLY, no other datums are impacted.
+ var/hijack_speed_override = 1
/datum/objective/hijack/check_completion() // Requires all owners to escape.
if(SSshuttle.emergency.mode != SHUTTLE_ENDGAME)
@@ -363,18 +365,33 @@ GLOBAL_LIST(admin_objective_list) //Prefilled admin assignable objective list
return FALSE
return SSshuttle.emergency.is_hijacked()
-/datum/objective/hijack/highlander
- name="highlander hijack"
- explanation_text = "Escape on the shuttle alone. Ensure that nobody else makes it out."
+/datum/objective/elimination
+ name = "elimination"
+ explanation_text = "Slaughter all loyalist crew aboard the shuttle. You, and any likeminded individuals, must be the only remaining people on the shuttle."
+ team_explanation_text = "Slaughter all loyalist crew aboard the shuttle. You, and any likeminded individuals, must be the only remaining people on the shuttle. Leave no team member behind."
+ martyr_compatible = FALSE
-/datum/objective/hijack/check_completion()
+/datum/objective/elimination/check_completion()
if(SSshuttle.emergency.mode != SHUTTLE_ENDGAME)
return FALSE
var/list/datum/mind/owners = get_owners()
for(var/datum/mind/M in owners)
if(!considered_alive(M, enforce_human = FALSE) || !SSshuttle.emergency.shuttle_areas[get_area(M.current)])
return FALSE
- return SSshuttle.emergency.is_hijacked(filter_by_human = FALSE, solo_hijack = TRUE)
+ return SSshuttle.emergency.elimination_hijack()
+
+/datum/objective/elimination/highlander
+ name="highlander elimination"
+ explanation_text = "Escape on the shuttle alone. Ensure that nobody else makes it out."
+
+/datum/objective/elimination/highlander/check_completion()
+ if(SSshuttle.emergency.mode != SHUTTLE_ENDGAME)
+ return FALSE
+ var/list/datum/mind/owners = get_owners()
+ for(var/datum/mind/M in owners)
+ if(!considered_alive(M, enforce_human = FALSE) || !SSshuttle.emergency.shuttle_areas[get_area(M.current)])
+ return FALSE
+ return SSshuttle.emergency.elimination_hijack(filter_by_human = FALSE, solo_hijack = TRUE)
/datum/objective/block
name = "no organics on shuttle"
diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm
index d1009dfe69c..301b677b14b 100644
--- a/code/modules/antagonists/_common/antag_datum.dm
+++ b/code/modules/antagonists/_common/antag_datum.dm
@@ -14,7 +14,9 @@ GLOBAL_LIST_EMPTY(antagonists)
var/list/objectives = list()
var/antag_memory = ""//These will be removed with antag datum
var/antag_moodlet //typepath of moodlet that the mob will gain with their status
- var/can_hijack = HIJACK_NEUTRAL //If these antags are alone on shuttle hijack happens.
+ var/can_elimination_hijack = ELIMINATION_NEUTRAL //If these antags are alone when a shuttle elimination happens.
+ /// If above 0, this is the multiplier for the speed at which we hijack the shuttle. Do not directly read, use hijack_speed().
+ var/hijack_speed = 0
var/antag_hud_type
var/antag_hud_name
@@ -264,6 +266,11 @@ GLOBAL_LIST_EMPTY(antagonists)
return
antag_memory = new_memo
+/// Gets how fast we can hijack the shuttle, return 0 for can not hijack. Defaults to hijack_speed var, override for custom stuff like buffing hijack speed for hijack objectives or something.
+/datum/antagonist/proc/hijack_speed()
+ var/datum/objective/hijack/H = locate() in objectives
+ return H?.hijack_speed_override || hijack_speed
+
//This one is created by admin tools for custom objectives
/datum/antagonist/custom
antagpanel_category = "Custom"
diff --git a/code/modules/antagonists/brother/brother.dm b/code/modules/antagonists/brother/brother.dm
index b6c32899577..ff78dc9e094 100644
--- a/code/modules/antagonists/brother/brother.dm
+++ b/code/modules/antagonists/brother/brother.dm
@@ -5,9 +5,9 @@
var/special_role = ROLE_BROTHER
antag_hud_type = ANTAG_HUD_BROTHER
antag_hud_name = "brother"
+ hijack_speed = 0.5
var/datum/team/brother_team/team
antag_moodlet = /datum/mood_event/focused
- can_hijack = HIJACK_HIJACKER
/datum/antagonist/brother/create_team(datum/team/brother_team/new_team)
if(!new_team)
diff --git a/code/modules/antagonists/changeling/changeling.dm b/code/modules/antagonists/changeling/changeling.dm
index 674b28ca70d..028055b3dfe 100644
--- a/code/modules/antagonists/changeling/changeling.dm
+++ b/code/modules/antagonists/changeling/changeling.dm
@@ -10,7 +10,7 @@
antag_moodlet = /datum/mood_event/focused
antag_hud_type = ANTAG_HUD_CHANGELING
antag_hud_name = "changeling"
-
+ hijack_speed = 0.5
var/you_are_greet = TRUE
var/give_objectives = TRUE
var/team_mode = FALSE //Should assign team objectives ?
diff --git a/code/modules/antagonists/eldritch_cult/eldritch_antag.dm b/code/modules/antagonists/eldritch_cult/eldritch_antag.dm
index b8a5abd9032..517fa7a1d1a 100644
--- a/code/modules/antagonists/eldritch_cult/eldritch_antag.dm
+++ b/code/modules/antagonists/eldritch_cult/eldritch_antag.dm
@@ -6,7 +6,7 @@
job_rank = ROLE_HERETIC
antag_hud_type = ANTAG_HUD_HERETIC
antag_hud_name = "heretic"
- can_hijack = HIJACK_HIJACKER
+ hijack_speed = 0.5
var/give_equipment = TRUE
var/list/researched_knowledge = list()
var/total_sacrifices = 0
diff --git a/code/modules/antagonists/eldritch_cult/eldritch_monster_antag.dm b/code/modules/antagonists/eldritch_cult/eldritch_monster_antag.dm
index e61a96ddd44..0629c70f832 100644
--- a/code/modules/antagonists/eldritch_cult/eldritch_monster_antag.dm
+++ b/code/modules/antagonists/eldritch_cult/eldritch_monster_antag.dm
@@ -2,7 +2,6 @@
/datum/antagonist/heretic_monster
name = "Eldritch Horror"
roundend_category = "Heretics"
- can_hijack = HIJACK_NEUTRAL
antagpanel_category = "Heretic Beast"
antag_moodlet = /datum/mood_event/heretics
job_rank = ROLE_HERETIC
diff --git a/code/modules/antagonists/ert/ert.dm b/code/modules/antagonists/ert/ert.dm
index 47282bb78be..d20a8480fe5 100644
--- a/code/modules/antagonists/ert/ert.dm
+++ b/code/modules/antagonists/ert/ert.dm
@@ -14,10 +14,10 @@
var/rip_and_tear = FALSE
var/equip_ert = TRUE
var/forge_objectives_for_ert = TRUE
+ can_elimination_hijack = ELIMINATION_PREVENT
show_in_antagpanel = FALSE
show_to_ghosts = TRUE
antag_moodlet = /datum/mood_event/focused
- can_hijack = HIJACK_PREVENT
/datum/antagonist/ert/on_gain()
if(random_names)
diff --git a/code/modules/antagonists/highlander/highlander.dm b/code/modules/antagonists/highlander/highlander.dm
index 4d82a5f3d91..0daf4f4d50b 100644
--- a/code/modules/antagonists/highlander/highlander.dm
+++ b/code/modules/antagonists/highlander/highlander.dm
@@ -3,7 +3,7 @@
var/obj/item/claymore/highlander/sword
show_in_antagpanel = FALSE
show_name_in_check_antagonists = TRUE
- can_hijack = HIJACK_HIJACKER
+ can_elimination_hijack = ELIMINATION_ENABLED
/datum/antagonist/highlander/apply_innate_effects(mob/living/mob_override)
var/mob/living/L = owner.current || mob_override
@@ -25,10 +25,9 @@
steal_objective.owner = owner
steal_objective.set_target(new /datum/objective_item/steal/nukedisc)
objectives += steal_objective
-
- var/datum/objective/hijack/highlander/hijack_objective = new
- hijack_objective.owner = owner
- objectives += hijack_objective
+ var/datum/objective/elimination/highlander/elimination_objective = new
+ elimination_objective.owner = owner
+ objectives += elimination_objective
/datum/antagonist/highlander/on_gain()
forge_objectives()
diff --git a/code/modules/antagonists/ninja/ninja.dm b/code/modules/antagonists/ninja/ninja.dm
index 110673043ae..8807898bf1b 100644
--- a/code/modules/antagonists/ninja/ninja.dm
+++ b/code/modules/antagonists/ninja/ninja.dm
@@ -13,7 +13,7 @@
/datum/antagonist/ninja/New()
if(helping_station)
- can_hijack = HIJACK_PREVENT
+ can_elimination_hijack = ELIMINATION_PREVENT
. = ..()
/datum/antagonist/ninja/apply_innate_effects(mob/living/mob_override)
@@ -145,7 +145,7 @@
else
return
if(helping_station)
- can_hijack = HIJACK_PREVENT
+ can_elimination_hijack = ELIMINATION_PREVENT
new_owner.assigned_role = ROLE_NINJA
new_owner.special_role = ROLE_NINJA
new_owner.add_antag_datum(src)
diff --git a/code/modules/antagonists/nukeop/nukeop.dm b/code/modules/antagonists/nukeop/nukeop.dm
index d795a2bd8c2..d71025179c2 100644
--- a/code/modules/antagonists/nukeop/nukeop.dm
+++ b/code/modules/antagonists/nukeop/nukeop.dm
@@ -7,11 +7,11 @@
antag_hud_name = "synd"
antag_moodlet = /datum/mood_event/focused
show_to_ghosts = TRUE
+ hijack_speed = 2 //If you can't take out the station, take the shuttle instead.
var/datum/team/nuclear/nuke_team
var/always_new_team = FALSE //If not assigned a team by default ops will try to join existing ones, set this to TRUE to always create new team.
var/send_to_spawnpoint = TRUE //Should the user be moved to default spawnpoint.
var/nukeop_outfit = /datum/outfit/syndicate
- can_hijack = HIJACK_HIJACKER //Alternative way to wipe out the station.
/datum/antagonist/nukeop/apply_innate_effects(mob/living/mob_override)
diff --git a/code/modules/antagonists/official/official.dm b/code/modules/antagonists/official/official.dm
index 182b678b8e4..9f17769c536 100644
--- a/code/modules/antagonists/official/official.dm
+++ b/code/modules/antagonists/official/official.dm
@@ -2,9 +2,9 @@
name = "CentCom Official"
show_name_in_check_antagonists = TRUE
show_in_antagpanel = FALSE
+ can_elimination_hijack = ELIMINATION_PREVENT
var/datum/objective/mission
var/datum/team/ert/ert_team
- can_hijack = HIJACK_PREVENT
show_to_ghosts = TRUE
/datum/antagonist/official/greet()
diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm
index ce25c32427f..089b455fb3a 100644
--- a/code/modules/antagonists/traitor/datum_traitor.dm
+++ b/code/modules/antagonists/traitor/datum_traitor.dm
@@ -9,6 +9,7 @@
antag_moodlet = /datum/mood_event/focused
antag_hud_type = ANTAG_HUD_TRAITOR
antag_hud_name = "traitor"
+ hijack_speed = 0.5 //10 seconds per hijack stage by default
var/special_role = ROLE_TRAITOR
var/employer = "The Syndicate"
var/give_objectives = TRUE
@@ -16,7 +17,6 @@
var/should_equip = TRUE
var/traitor_kind = TRAITOR_HUMAN //Set on initial assignment
var/datum/contractor_hub/contractor_hub
- can_hijack = HIJACK_HIJACKER
/datum/antagonist/traitor/on_gain()
if(owner.current && isAI(owner.current))
diff --git a/code/modules/antagonists/wishgranter/wishgranter.dm b/code/modules/antagonists/wishgranter/wishgranter.dm
index f17b9497806..67a6153f7bb 100644
--- a/code/modules/antagonists/wishgranter/wishgranter.dm
+++ b/code/modules/antagonists/wishgranter/wishgranter.dm
@@ -2,7 +2,7 @@
name = "Wishgranter Avatar"
show_in_antagpanel = FALSE
show_name_in_check_antagonists = TRUE
- can_hijack = HIJACK_HIJACKER
+ hijack_speed = 2 //You literally are here to do nothing else. Might as well be fast about it.
/datum/antagonist/wishgranter/proc/forge_objectives()
var/datum/objective/hijack/hijack = new
diff --git a/code/modules/antagonists/wizard/wizard.dm b/code/modules/antagonists/wizard/wizard.dm
index ce92e0f799b..542aba428cb 100644
--- a/code/modules/antagonists/wizard/wizard.dm
+++ b/code/modules/antagonists/wizard/wizard.dm
@@ -6,6 +6,7 @@
antag_hud_type = ANTAG_HUD_WIZ
antag_hud_name = "wizard"
antag_moodlet = /datum/mood_event/focused
+ hijack_speed = 0.5
var/give_objectives = TRUE
var/strip = TRUE //strip before equipping
var/allow_rename = TRUE
@@ -13,7 +14,6 @@
var/move_to_lair = TRUE
var/outfit_type = /datum/outfit/wizard
var/wiz_age = WIZARD_AGE_MIN /* Wizards by nature cannot be too young. */
- can_hijack = HIJACK_HIJACKER
show_to_ghosts = TRUE
/datum/antagonist/wizard/on_gain()
diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm
index f8386247382..19837571b07 100644
--- a/code/modules/shuttle/emergency.dm
+++ b/code/modules/shuttle/emergency.dm
@@ -4,15 +4,39 @@
#define IS_DOCKED (SSshuttle.emergency.mode == SHUTTLE_DOCKED || (ENGINES_STARTED))
#define SHUTTLE_CONSOLE_ACTION_DELAY (5 SECONDS)
+#define NOT_BEGUN 0
+#define STAGE_1 1
+#define STAGE_2 2
+#define STAGE_3 3
+#define STAGE_4 4
+#define HIJACKED 5
+
/obj/machinery/computer/emergency_shuttle
name = "emergency shuttle console"
desc = "For shuttle control."
icon_screen = "shuttle"
icon_keyboard = "tech_key"
-
+ resistance_flags = INDESTRUCTIBLE
var/auth_need = 3
var/list/authorized = list()
var/list/acted_recently = list()
+ var/hijack_last_stage_increase = 0 SECONDS
+ var/hijack_stage_time = 5 SECONDS
+ var/hijack_stage_cooldown = 5 SECONDS
+ var/hijack_flight_time_increase = 30 SECONDS
+ var/hijack_completion_flight_time_set = 10 SECONDS //How long in deciseconds to set shuttle's timer after hijack is done.
+ var/hijack_hacking = FALSE
+ var/hijack_announce = TRUE
+
+/obj/machinery/computer/emergency_shuttle/examine(mob/user)
+ . = ..()
+ if(hijack_announce)
+ . += "Security systems present on console. Any unauthorized tampering will result in an emergency announcement."
+ if(user?.mind?.get_hijack_speed())
+ . += "Alt click on this to attempt to hijack the shuttle. This will take multiple tries (current: stage [SSshuttle.emergency.hijack_status]/[HIJACKED])."
+ . += "It will take you [(hijack_stage_time * user.mind.get_hijack_speed()) / 10] seconds to reprogram a stage of the shuttle's navigational firmware, and the console will undergo automated timed lockout for [hijack_stage_cooldown/10] seconds after each stage."
+ if(hijack_announce)
+ . += "It is probably best to fortify your position as to be uninterrupted during the attempt, given the automatic announcements.."
/obj/machinery/computer/emergency_shuttle/attackby(obj/item/I, mob/user,params)
if(istype(I, /obj/item/card/id))
@@ -152,6 +176,67 @@
[TIME_LEFT] seconds", system_error, alert=TRUE)
. = TRUE
+/obj/machinery/computer/emergency_shuttle/proc/increase_hijack_stage()
+ var/obj/docking_port/mobile/emergency/shuttle = SSshuttle.emergency
+ shuttle.hijack_status++
+ if(hijack_announce)
+ announce_hijack_stage()
+ hijack_last_stage_increase = world.time
+ say("Navigational protocol error! Rebooting systems.")
+ if(shuttle.mode == SHUTTLE_ESCAPE)
+ if(shuttle.hijack_status == HIJACKED)
+ shuttle.setTimer(hijack_completion_flight_time_set)
+ else
+ shuttle.setTimer(shuttle.timeLeft(1) + hijack_flight_time_increase) //give the guy more time to hijack if it's already in flight.
+ return shuttle.hijack_status
+
+/obj/machinery/computer/emergency_shuttle/AltClick(user)
+ if(isliving(user))
+ attempt_hijack_stage(user)
+
+/obj/machinery/computer/emergency_shuttle/proc/attempt_hijack_stage(mob/living/user)
+ if(!user.CanReach(src))
+ return
+ if(!user?.mind?.get_hijack_speed())
+ to_chat(user, "You manage to open a user-mode shell on [src], and hundreds of lines of debugging output fly through your vision. It is probably best to leave this alone.= HIJACKED)
+ to_chat(user, "The emergency shuttle is already loaded with a corrupt navigational payload. What more do you want from it?")
+ return
+ if(hijack_last_stage_increase >= world.time + hijack_stage_cooldown)
+ say("Error - Catastrophic software error detected. Input is currently on timeout.")
+ return
+ hijack_hacking = TRUE
+ to_chat(user, "You [SSshuttle.emergency.hijack_status == NOT_BEGUN? "begin" : "continue"] to override [src]'s navigational protocols.")
+ say("Software override initiated.")
+ . = FALSE
+ if(do_after(user, hijack_stage_time * (1 / user.mind.get_hijack_speed()), target = src))
+ increase_hijack_stage()
+ . = TRUE
+ to_chat(user, "You reprogram some of [src]'s programming, putting it on timeout for [hijack_stage_cooldown/10] seconds.")
+ hijack_hacking = FALSE
+
+/obj/machinery/computer/emergency_shuttle/proc/announce_hijack_stage()
+ var/msg
+ switch(SSshuttle.emergency.hijack_status)
+ if(NOT_BEGUN)
+ return
+ if(STAGE_1)
+ msg = "AUTHENTICATING - FAIL. AUTHENTICATING - FAIL. AUTHENTICATING - FAI###### Welcome, technician JOHN DOE."
+ if(STAGE_2)
+ msg = "Warning: Navigational route fails \"IS_AUTHORIZED\". Please try againNN[scramble_message_replace_chars("againagainagainagainagain", 70)]."
+ if(STAGE_3)
+ msg = "CRC mismatch at ~h~ in calculated route buffer. Full reset initiated of FTL_NAVIGATION_SERVICES. Memory decrypted for automatic repair."
+ if(STAGE_4)
+ msg = "~ACS_directive module_load(cyberdyne.exploit.nanotrasen.shuttlenav)... NT key mismatch. Confirm load? Y...###Reboot complete. $SET transponder_state = 0; System link initiated with connected engines..."
+ if(HIJACKED)
+ msg = "SYSTEM OVERRIDE - Resetting course to \[[scramble_message_replace_chars("###########", 100)]\] \
+ ([scramble_message_replace_chars("#######", 100)]/[scramble_message_replace_chars("#######", 100)]/[scramble_message_replace_chars("#######", 100)]) \
+ {AUTH - ROOT (uid: 0)}.[SSshuttle.emergency.mode == SHUTTLE_ESCAPE ? "Diverting from existing route - Bluespace exit in [hijack_completion_flight_time_set/10] seconds." : ""]"
+ minor_announce(scramble_message_replace_chars(msg, replaceprob = 10), "Emergency Shuttle", TRUE)
+
/obj/machinery/computer/emergency_shuttle/emag_act(mob/user)
// How did you even get on the shuttle before it go to the station?
if(!IS_DOCKED)
@@ -202,6 +287,7 @@
dir = EAST
port_direction = WEST
var/sound_played = 0 //If the launch sound has been sent to all players on the shuttle itself
+ var/hijack_status = NOT_BEGUN
/obj/docking_port/mobile/emergency/canDock(obj/docking_port/stationary/S)
return SHUTTLE_CAN_DOCK //If the emergency shuttle can't move, the whole game breaks, so it will force itself to land even if it has to crush a few departments in the process
@@ -265,9 +351,8 @@
SSticker.emergency_reason = null
-
/**
- * Proc that handles checking if the emergency shuttle was successfully hijacked
+ * Proc that handles checking if the emergency shuttle was successfully hijacked via being the only people present on the shuttle for the elimination hijack or highlander objective
*
* Checks for all mobs on the shuttle, checks their status, and checks if they're
* borgs or simple animals. Depending on the args, certain mobs may be ignored,
@@ -276,7 +361,7 @@
* filter_by_human, default TRUE, tells the proc that only humans should block a hijack. Borgs and animals are ignored and will not block if this is TRUE.
* solo_hijack, default FALSE, tells the proc to fail with multiple hijackers, such as for Highlander mode.
*/
-/obj/docking_port/mobile/emergency/proc/is_hijacked(filter_by_human = TRUE, solo_hijack = FALSE)
+/obj/docking_port/mobile/emergency/proc/elimination_hijack(filter_by_human = TRUE, solo_hijack = FALSE)
var/has_people = FALSE
var/hijacker_count = 0
for(var/mob/living/player in GLOB.player_list)
@@ -297,11 +382,11 @@
//Antag present, doesn't stop but let's see if we actually want to hijack
var/prevent = FALSE
for(var/datum/antagonist/A in player.mind.antag_datums)
- if(A.can_hijack == HIJACK_HIJACKER)
+ if(A.can_elimination_hijack == ELIMINATION_ENABLED)
hijacker_count += 1
prevent = FALSE
break //If we have both prevent and hijacker antags assume we want to hijack.
- else if(A.can_hijack == HIJACK_PREVENT)
+ else if(A.can_elimination_hijack == ELIMINATION_PREVENT)
prevent = TRUE
if(prevent)
return FALSE
@@ -309,6 +394,9 @@
//has people AND either there's only one hijacker or there's any but solo_hijack is disabled
return has_people && ((hijacker_count == 1) || (hijacker_count && !solo_hijack))
+/obj/docking_port/mobile/emergency/proc/is_hijacked()
+ return hijack_status == HIJACKED
+
/obj/docking_port/mobile/emergency/proc/ShuttleDBStuff()
set waitfor = FALSE
if(!SSdbcore.Connect())
@@ -437,7 +525,7 @@
// now move the actual emergency shuttle to centcom
// unless the shuttle is "hijacked"
var/destination_dock = "emergency_away"
- if(is_hijacked())
+ if(is_hijacked() && elimination_hijack())
destination_dock = "emergency_syndicate"
minor_announce("Corruption detected in \
shuttle navigation protocols. Please contact your \
@@ -454,7 +542,7 @@
mode = SHUTTLE_ESCAPE
launch_status = ENDGAME_LAUNCHED
setTimer(SSshuttle.emergencyEscapeTime)
- priority_announce("The Emergency Shuttle preparing for direct jump. Estimate [timeLeft(600)] minutes until the shuttle docks at Central Command.", null, null, "Priority")
+ priority_announce("The Emergency Shuttle is preparing for direct jump. Estimate [timeLeft(600)] minutes until the shuttle docks at Central Command.", null, null, "Priority")
/obj/docking_port/mobile/pod
@@ -629,3 +717,10 @@
#undef ENGINES_STARTED
#undef IS_DOCKED
#undef SHUTTLE_CONSOLE_ACTION_DELAY
+
+#undef NOT_BEGUN
+#undef STAGE_1
+#undef STAGE_2
+#undef STAGE_3
+#undef STAGE_4
+#undef HIJACKED