mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-22 05:25:15 +01:00
Replaceable Traitor Uplinks (#74315)
## About The Pull Request Following [from the suggestion in this hackmd ](https://hackmd.io/IkDWWkpfQa2lkdevsnLqhA?view#Replacement-Uplinks)with a few twists of my own, I have made a method for traitors to acquire a replacement traitor uplink that has its own set of flaws and limiters in order to prevent abuse.  The basic pitch is as follows, all traitors now start with a new, crafting recipe exclusive to them, it costs a teleport beacon, a bluespace crystal, and some iron and cable coil, and then allows them to build a static, dense machine that they can synchronize with, which allows the machine to know what signal it should be looking out for from the traitor.  The traitor then uses any radio, sets it to the frequency that has been added to their static antagonist ui, and then speaks their codeword, also in the ui, and then a few things happen.  Most obviously, they get a replacement uplink that is in the conspicuous shape of the nukie or lone op uplink. This uplink can be unlocked by speaking your replacement codeword to it again, it remembers your previous TC amount and locks all other uplinks associated with your uplink handler(they can then be unlocked as normal). It also destroys any other replacement uplinks associated with your uplink handler, which means you can never have more than one replacement uplink. This means that if your uplink has been confiscated and you left it unlocked, if it hasn't been emptied out you can continue from where you were, and if you want to get back on the TC grind you won't lose the new TC to whoever stole your uplink. Of course, the new uplink can not be locked, so you have to be more careful with it or buy an uplink implant and destroy it. You can destroy your replacement uplink with a screwdriver right click, same for the machine. Additionally, the Syndicate Uplink Beacon has another quirk to it, which is that the teleporter beacon used to create it is intact, which means people eagle eyed on the teleporter console could go find you, not to mention that if you use an existing teleporter beacon, someone might notice its gone missing... oh also while making the replacement uplink i found a bug caused by a recent pr that broke debug uplinks due to them not having a purchase log. thats fixed too ## Why It's Good For The Game It can be easy to lose your uplink, and as a traitor having your uplink confiscated, even if it is locked, feels really bad. While the old traitor objectives were added back to prog traitor to prevent situations where a confiscated uplink meant that you were completely aimless, I think that having a backup solution would be good for more inexperienced traitors or for ones who get unlucky. Hopefully this is generally balanced well enough but there are a few levers that can be pulled, but overall I do think that making it so that traitors can always get a chance to get an uplink and do some objectives is good for the game. I like the idea of someone getting perma'd, someone breaks them out, they both craft a new uplink beacon, and then they go back and get the traitors old gear with stuff they got from the new uplink, I think that's a cool possibility to throw into the sandbox. ## Changelog 🆑 add: Added new syndicate uplink beacon and associated systems that allow you to get a replacement traitor uplink fix: Debug & nukie uplinks no longer runtime and work properly again /🆑
This commit is contained in:
@@ -3,6 +3,8 @@
|
||||
|
||||
/// Called whenever the uplink handler receives any sort of update. Used by uplinks to update their UI. No arguments passed
|
||||
#define COMSIG_UPLINK_HANDLER_ON_UPDATE "uplink_handler_on_update"
|
||||
/// Sent from the uplink handler when the traitor uses the syndicate uplink beacon to order a replacement uplink.
|
||||
#define COMSIG_UPLINK_HANDLER_REPLACEMENT_ORDERED "uplink_handler_replacement_ordered"
|
||||
|
||||
/// Called before the traitor objective is generated
|
||||
#define COMSIG_TRAITOR_OBJECTIVE_PRE_GENERATE "traitor_objective_pre_generate"
|
||||
|
||||
@@ -90,6 +90,8 @@
|
||||
#define FREQ_SIGNALER 1457 // the default for new signalers
|
||||
#define FREQ_COMMON 1459 // Common comms frequency, dark green
|
||||
|
||||
#define MIN_UNUSED_FREQ 1461 // Prevents rolling AI Private or Common
|
||||
|
||||
#define MAX_FREQ 1489 // ------------------------------------------------------
|
||||
|
||||
#define MAX_FREE_FREQ 1599 // -------------------------------------------------
|
||||
|
||||
@@ -605,10 +605,15 @@
|
||||
|
||||
//Mind helpers
|
||||
|
||||
/datum/mind/proc/teach_crafting_recipe(R)
|
||||
/// proc that teaches user a non-standard crafting recipe
|
||||
/datum/mind/proc/teach_crafting_recipe(recipe)
|
||||
if(!learned_recipes)
|
||||
learned_recipes = list()
|
||||
learned_recipes |= R
|
||||
learned_recipes |= recipe
|
||||
|
||||
/// proc that makes user forget a specific crafting recipe
|
||||
/datum/mind/proc/forget_crafting_recipe(recipe)
|
||||
learned_recipes -= recipe
|
||||
|
||||
/datum/mind/proc/has_crafting_recipe(mob/user, potential_recipe)
|
||||
if(!learned_recipes)
|
||||
|
||||
@@ -60,3 +60,17 @@
|
||||
/obj/item/stack/cable_coil = 10,
|
||||
)
|
||||
category = CAT_STRUCTURE
|
||||
|
||||
/datum/crafting_recipe/syndicate_uplink_beacon
|
||||
name = "Syndicate Uplink Beacon"
|
||||
result = /obj/structure/syndicate_uplink_beacon
|
||||
tool_behaviors = list(TOOL_SCREWDRIVER)
|
||||
always_available = FALSE
|
||||
time = 6 SECONDS
|
||||
reqs = list(
|
||||
/obj/item/stack/sheet/iron = 5,
|
||||
/obj/item/stack/cable_coil = 5,
|
||||
/obj/item/beacon = 1,
|
||||
/obj/item/stack/ore/bluespace_crystal = 1,
|
||||
)
|
||||
category = CAT_STRUCTURE
|
||||
|
||||
@@ -65,6 +65,8 @@
|
||||
RegisterSignal(parent, COMSIG_RADIO_NEW_MESSAGE, PROC_REF(new_message))
|
||||
else if(istype(parent, /obj/item/pen))
|
||||
RegisterSignal(parent, COMSIG_PEN_ROTATED, PROC_REF(pen_rotation))
|
||||
else if(istype(parent, /obj/item/uplink/replacement))
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_HEAR, PROC_REF(on_heard))
|
||||
|
||||
if(owner)
|
||||
src.owner = owner
|
||||
@@ -86,6 +88,7 @@
|
||||
else
|
||||
uplink_handler = uplink_handler_override
|
||||
RegisterSignal(uplink_handler, COMSIG_UPLINK_HANDLER_ON_UPDATE, PROC_REF(handle_uplink_handler_update))
|
||||
RegisterSignal(uplink_handler, COMSIG_UPLINK_HANDLER_REPLACEMENT_ORDERED, PROC_REF(handle_uplink_replaced))
|
||||
if(!lockable)
|
||||
active = TRUE
|
||||
locked = FALSE
|
||||
@@ -96,6 +99,19 @@
|
||||
SIGNAL_HANDLER
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/// When a new uplink is made via the syndicate beacon it locks all lockable uplinks and destroys replacement uplinks
|
||||
/datum/component/uplink/proc/handle_uplink_replaced()
|
||||
SIGNAL_HANDLER
|
||||
if(lockable)
|
||||
lock_uplink()
|
||||
if(!istype(parent, /obj/item/uplink/replacement))
|
||||
return
|
||||
var/obj/item/uplink_item = parent
|
||||
do_sparks(number = 3, cardinal_only = FALSE, source = uplink_item)
|
||||
uplink_item.visible_message(span_warning("The [uplink_item] suddenly combusts!"), vision_distance = COMBAT_MESSAGE_RANGE)
|
||||
new /obj/effect/decal/cleanable/ash(get_turf(uplink_item))
|
||||
qdel(uplink_item)
|
||||
|
||||
/// Adds telecrystals to the uplink. It is bad practice to use this outside of the component itself.
|
||||
/datum/component/uplink/proc/add_telecrystals(telecrystals_added)
|
||||
set_telecrystals(uplink_handler.telecrystals + telecrystals_added)
|
||||
@@ -236,7 +252,7 @@
|
||||
data["extra_purchasable_stock"] = extra_purchasable_stock
|
||||
data["current_stock"] = remaining_stock
|
||||
data["shop_locked"] = uplink_handler.shop_locked
|
||||
data["purchased_items"] = length(uplink_handler.purchase_log.purchase_log)
|
||||
data["purchased_items"] = length(uplink_handler.purchase_log?.purchase_log)
|
||||
return data
|
||||
|
||||
/datum/component/uplink/ui_static_data(mob/user)
|
||||
@@ -277,9 +293,7 @@
|
||||
if("lock")
|
||||
if(!lockable)
|
||||
return TRUE
|
||||
active = FALSE
|
||||
locked = TRUE
|
||||
SStgui.close_uis(src)
|
||||
lock_uplink()
|
||||
|
||||
if(!uplink_handler.has_objectives)
|
||||
return TRUE
|
||||
@@ -321,6 +335,12 @@
|
||||
uplink_handler.abort_objective(objective)
|
||||
return TRUE
|
||||
|
||||
/// Proc that locks uplinks
|
||||
/datum/component/uplink/proc/lock_uplink()
|
||||
active = FALSE
|
||||
locked = TRUE
|
||||
SStgui.close_uis(src)
|
||||
|
||||
// Implant signal responses
|
||||
/datum/component/uplink/proc/implant_activation()
|
||||
SIGNAL_HANDLER
|
||||
@@ -459,6 +479,17 @@
|
||||
|
||||
return returnable_code
|
||||
|
||||
/// Proc that unlocks a locked replacement uplink when it hears the unlock code from their datum
|
||||
/datum/component/uplink/proc/on_heard(datum/source, list/hearing_args)
|
||||
SIGNAL_HANDLER
|
||||
if(!locked)
|
||||
return
|
||||
if(!findtext(hearing_args[HEARING_RAW_MESSAGE], unlock_code))
|
||||
return
|
||||
var/atom/replacement_uplink = parent
|
||||
locked = FALSE
|
||||
replacement_uplink.balloon_alert_to_viewers("beep", vision_distance = COMBAT_MESSAGE_RANGE)
|
||||
|
||||
/datum/component/uplink/proc/failsafe(mob/living/carbon/user)
|
||||
if(!parent)
|
||||
return
|
||||
|
||||
@@ -132,3 +132,16 @@
|
||||
mid_sounds = list('sound/effects/bubbles2.ogg' = 1)
|
||||
mid_length = 7 SECONDS
|
||||
volume = 25
|
||||
|
||||
/datum/looping_sound/typing
|
||||
mid_sounds = list(
|
||||
'sound/machines/terminal_button01.ogg' = 1,
|
||||
'sound/machines/terminal_button02.ogg' = 1,
|
||||
'sound/machines/terminal_button03.ogg' = 1,
|
||||
'sound/machines/terminal_button04.ogg' = 1,
|
||||
'sound/machines/terminal_button05.ogg' = 1,
|
||||
'sound/machines/terminal_button06.ogg' = 1,
|
||||
'sound/machines/terminal_button07.ogg' = 1,
|
||||
'sound/machines/terminal_button08.ogg' = 1,
|
||||
)
|
||||
mid_length = 0.3 SECONDS
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/// Device that traitors can craft in order to be sent a new, undisguised uplink
|
||||
/obj/structure/syndicate_uplink_beacon
|
||||
name = "suspicious beacon"
|
||||
icon = 'icons/obj/machines/telecomms.dmi'
|
||||
icon_state = "relay_traitor"
|
||||
desc = "This ramshackle device seems capable of recieving and sending signals for some nefarious purpose."
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
/// Traitor's code that they speak into the radio
|
||||
var/uplink_code = ""
|
||||
/// weakref to person who is going to use the beacon to get a replacement uplink
|
||||
var/datum/weakref/owner
|
||||
/// while constructed the teleport beacon is still active
|
||||
var/obj/item/beacon/teleport_beacon
|
||||
/// Radio that the device needs to listen to the codeword from the traitor
|
||||
var/obj/item/radio/listening_radio
|
||||
/// prevents traitor from activating teleport_beacon proc too much in a small period of time
|
||||
COOLDOWN_DECLARE(beacon_cooldown)
|
||||
|
||||
/obj/structure/syndicate_uplink_beacon/Initialize(mapload)
|
||||
. = ..()
|
||||
register_context()
|
||||
|
||||
var/static/list/tool_behaviors = list(
|
||||
TOOL_SCREWDRIVER = list(
|
||||
SCREENTIP_CONTEXT_RMB = "Deconstruct",
|
||||
),
|
||||
)
|
||||
AddElement(/datum/element/contextual_screentip_tools, tool_behaviors)
|
||||
listening_radio = new(src)
|
||||
listening_radio.canhear_range = 0
|
||||
teleport_beacon = new(src)
|
||||
|
||||
/obj/structure/syndicate_uplink_beacon/attack_hand(mob/living/user, list/modifiers)
|
||||
if(!IS_TRAITOR(user))
|
||||
balloon_alert(user, "don't know how to use!")
|
||||
return
|
||||
if(IS_WEAKREF_OF(owner, user))
|
||||
balloon_alert(user, "already synchronized to you!")
|
||||
return
|
||||
if(owner != null)
|
||||
balloon_alert(user, "already claimed!")
|
||||
return
|
||||
var/datum/looping_sound/typing/typing_sounds = new(src, start_immediately = TRUE)
|
||||
balloon_alert(user, "synchronizing...")
|
||||
if(!do_after(user = user, delay = 3 SECONDS, target = src, interaction_key = REF(src)))
|
||||
typing_sounds.stop()
|
||||
return
|
||||
typing_sounds.stop()
|
||||
probe_traitor(user)
|
||||
|
||||
/obj/structure/syndicate_uplink_beacon/screwdriver_act_secondary(mob/living/user, obj/item/tool)
|
||||
tool.play_tool_sound(src)
|
||||
balloon_alert(user, "deconstructing...")
|
||||
if (!do_after(user, 5 SECONDS, target = src))
|
||||
return FALSE
|
||||
var/turf/beacon_tile = get_turf(src)
|
||||
new /obj/item/stack/sheet/iron/five(beacon_tile)
|
||||
new /obj/item/stack/cable_coil/five(beacon_tile)
|
||||
teleport_beacon.forceMove(beacon_tile)
|
||||
teleport_beacon = null
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
/obj/structure/syndicate_uplink_beacon/Destroy()
|
||||
QDEL_NULL(listening_radio)
|
||||
if(teleport_beacon)
|
||||
QDEL_NULL(teleport_beacon)
|
||||
return ..()
|
||||
|
||||
/// Proc reads the user, sets radio to the correct frequency and starts to listen for the replacement uplink code
|
||||
/obj/structure/syndicate_uplink_beacon/proc/probe_traitor(mob/living/user)
|
||||
owner = WEAKREF(user)
|
||||
var/datum/antagonist/traitor/traitor_datum = user.mind.has_antag_datum(/datum/antagonist/traitor)
|
||||
|
||||
uplink_code = traitor_datum.replacement_uplink_code
|
||||
listening_radio.set_frequency(traitor_datum.replacement_uplink_frequency)
|
||||
become_hearing_sensitive()
|
||||
|
||||
/obj/structure/syndicate_uplink_beacon/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, list/message_mods, message_range)
|
||||
if(ismob(speaker) || radio_freq != listening_radio.get_frequency())
|
||||
return
|
||||
if(!findtext(message, uplink_code))
|
||||
return
|
||||
teleport_uplink()
|
||||
|
||||
/// Proc uses owners uplink handler to create replacement uplink and then lock or destroy their other uplinks
|
||||
/obj/structure/syndicate_uplink_beacon/proc/teleport_uplink()
|
||||
if(!COOLDOWN_FINISHED(src, beacon_cooldown))
|
||||
return
|
||||
COOLDOWN_START(src, beacon_cooldown, 10 MINUTES)
|
||||
|
||||
var/mob/living/resolved_owner = owner.resolve()
|
||||
if(isnull(resolved_owner))
|
||||
return
|
||||
|
||||
var/datum/antagonist/traitor/traitor_datum = resolved_owner.mind.has_antag_datum(/datum/antagonist/traitor)
|
||||
if(isnull(traitor_datum))
|
||||
return
|
||||
|
||||
var/datum/uplink_handler/uplink_handler = traitor_datum.uplink_handler
|
||||
|
||||
SEND_SIGNAL(uplink_handler, COMSIG_UPLINK_HANDLER_REPLACEMENT_ORDERED)
|
||||
new /obj/item/uplink/replacement(get_turf(src), /*owner = */resolved_owner, /*tc_amount = */0, /*uplink_handler_override = */uplink_handler)
|
||||
flick("relay_traitor_activate", src)
|
||||
do_sparks(number = 5, cardinal_only = FALSE, source = src)
|
||||
log_traitor("[key_name(resolved_owner)] acquired a replacement uplink via the syndicate uplink beacon.")
|
||||
|
||||
// Adds screentips
|
||||
/obj/structure/syndicate_uplink_beacon/add_context(atom/source, list/context, obj/item/held_item, mob/user)
|
||||
if(held_item || !IS_TRAITOR(user))
|
||||
return NONE
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Synchronize with beacon"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
@@ -18,6 +18,10 @@
|
||||
var/should_give_codewords = TRUE
|
||||
///give this traitor an uplink?
|
||||
var/give_uplink = TRUE
|
||||
/// Code that allows traitor to get a replacement uplink
|
||||
var/replacement_uplink_code = ""
|
||||
/// Radio frequency that traitor must speak on to get a replacement uplink
|
||||
var/replacement_uplink_frequency = ""
|
||||
///if TRUE, this traitor will always get hijacking as their final objective
|
||||
var/is_hijacker = FALSE
|
||||
|
||||
@@ -47,6 +51,7 @@
|
||||
|
||||
if(give_uplink)
|
||||
owner.give_uplink(silent = TRUE, antag_datum = src)
|
||||
generate_replacement_codes()
|
||||
|
||||
var/datum/component/uplink/uplink = owner.find_syndicate_uplink()
|
||||
uplink_ref = WEAKREF(uplink)
|
||||
@@ -82,6 +87,8 @@
|
||||
|
||||
pick_employer()
|
||||
|
||||
owner.teach_crafting_recipe(/datum/crafting_recipe/syndicate_uplink_beacon)
|
||||
|
||||
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/tatoralert.ogg', 100, FALSE, pressure_affected = FALSE, use_reverb = FALSE)
|
||||
|
||||
return ..()
|
||||
@@ -139,8 +146,14 @@
|
||||
result += "<a href='?src=[REF(owner)];common=give_objective'>Force add objective</a><br>"
|
||||
return result
|
||||
|
||||
/// proc that generates the traitors replacement uplink code and radio frequency
|
||||
/datum/antagonist/traitor/proc/generate_replacement_codes()
|
||||
replacement_uplink_code = "[pick(GLOB.phonetic_alphabet)] [rand(10,99)]"
|
||||
replacement_uplink_frequency = sanitize_frequency(rand(MIN_UNUSED_FREQ, MAX_FREQ), free = FALSE, syndie = FALSE)
|
||||
|
||||
/datum/antagonist/traitor/on_removal()
|
||||
owner.special_role = null
|
||||
owner.forget_crafting_recipe(/datum/crafting_recipe/syndicate_uplink_beacon)
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/traitor/proc/pick_employer()
|
||||
@@ -258,6 +271,8 @@
|
||||
data["theme"] = traitor_flavor["ui_theme"]
|
||||
data["code"] = uplink?.unlock_code
|
||||
data["failsafe_code"] = uplink?.failsafe_code
|
||||
data["replacement_code"] = replacement_uplink_code
|
||||
data["replacement_frequency"] = format_frequency(replacement_uplink_frequency)
|
||||
data["intro"] = traitor_flavor["introduction"]
|
||||
data["allies"] = traitor_flavor["allies"]
|
||||
data["goal"] = traitor_flavor["goal"]
|
||||
|
||||
@@ -23,15 +23,25 @@
|
||||
/// The uplink flag for this type.
|
||||
/// See [`code/__DEFINES/uplink.dm`]
|
||||
var/uplink_flag = UPLINK_TRAITORS
|
||||
/// If the uplink is lockable, which defaults to false which most subtypes of this item are for debug reasons
|
||||
var/lockable_uplink = FALSE
|
||||
|
||||
/obj/item/uplink/Initialize(mapload, owner, tc_amount = 20)
|
||||
/obj/item/uplink/Initialize(mapload, owner, tc_amount = 20, datum/uplink_handler/uplink_handler_override = null)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/uplink, owner, FALSE, TRUE, uplink_flag, tc_amount)
|
||||
AddComponent(\
|
||||
/datum/component/uplink, \
|
||||
owner = owner, \
|
||||
lockable = lockable_uplink, \
|
||||
enabled = TRUE, \
|
||||
uplink_flag = uplink_flag, \
|
||||
starting_tc = tc_amount, \
|
||||
uplink_handler_override = uplink_handler_override, \
|
||||
)
|
||||
|
||||
/obj/item/uplink/debug
|
||||
name = "debug uplink"
|
||||
|
||||
/obj/item/uplink/debug/Initialize(mapload, owner, tc_amount = 9000)
|
||||
/obj/item/uplink/debug/Initialize(mapload, owner, tc_amount = 9000, datum/uplink_handler/uplink_handler_override = null)
|
||||
. = ..()
|
||||
var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink)
|
||||
hidden_uplink.name = "debug uplink"
|
||||
@@ -44,7 +54,7 @@
|
||||
name = "debug nuclear uplink"
|
||||
uplink_flag = UPLINK_NUKE_OPS
|
||||
|
||||
/obj/item/uplink/nuclear/debug/Initialize(mapload, owner, tc_amount = 9000)
|
||||
/obj/item/uplink/nuclear/debug/Initialize(mapload, owner, tc_amount = 9000, datum/uplink_handler/uplink_handler_override = null)
|
||||
. = ..()
|
||||
var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink)
|
||||
hidden_uplink.name = "debug nuclear uplink"
|
||||
@@ -65,17 +75,45 @@
|
||||
name = "dusty radio"
|
||||
desc = "A dusty looking radio."
|
||||
|
||||
/obj/item/uplink/old/Initialize(mapload, owner, tc_amount = 10)
|
||||
/obj/item/uplink/old/Initialize(mapload, owner, tc_amount = 10, datum/uplink_handler/uplink_handler_override = null)
|
||||
. = ..()
|
||||
var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink)
|
||||
hidden_uplink.name = "dusty radio"
|
||||
|
||||
// Uplink subtype used as replacement uplink
|
||||
/obj/item/uplink/replacement
|
||||
lockable_uplink = TRUE
|
||||
|
||||
/obj/item/uplink/replacement/Initialize(mapload, owner, tc_amount = 10, datum/uplink_handler/uplink_handler_override = null)
|
||||
. = ..()
|
||||
var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink)
|
||||
var/mob/living/replacement_needer = owner
|
||||
if(!istype(replacement_needer))
|
||||
return
|
||||
var/datum/antagonist/traitor/traitor_datum = replacement_needer?.mind.has_antag_datum(/datum/antagonist/traitor)
|
||||
hidden_uplink.unlock_code = traitor_datum?.replacement_uplink_code
|
||||
become_hearing_sensitive()
|
||||
|
||||
/obj/item/uplink/replacement/screwdriver_act_secondary(mob/living/user, obj/item/tool)
|
||||
tool.play_tool_sound(src)
|
||||
balloon_alert(user, "deconstructing...")
|
||||
if (!do_after(user, 3 SECONDS, target = src))
|
||||
return FALSE
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
/obj/item/uplink/replacement/examine(mob/user)
|
||||
. = ..()
|
||||
if(!IS_TRAITOR(user))
|
||||
return
|
||||
. += span_notice("You can destroy this device with a screwdriver.")
|
||||
|
||||
// Multitool uplink
|
||||
/obj/item/multitool/uplink/Initialize(mapload, owner, tc_amount = 20)
|
||||
/obj/item/multitool/uplink/Initialize(mapload, owner, tc_amount = 20, datum/uplink_handler/uplink_handler_override = null)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/uplink, owner, FALSE, TRUE, UPLINK_TRAITORS, tc_amount)
|
||||
|
||||
// Pen uplink
|
||||
/obj/item/pen/uplink/Initialize(mapload, owner, tc_amount = 20)
|
||||
/obj/item/pen/uplink/Initialize(mapload, owner, tc_amount = 20, datum/uplink_handler/uplink_handler_override = null)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/uplink, owner, TRUE, FALSE, UPLINK_TRAITORS, tc_amount)
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 25 KiB |
@@ -2135,6 +2135,7 @@
|
||||
#include "code\game\objects\structures\spawner.dm"
|
||||
#include "code\game\objects\structures\spirit_board.dm"
|
||||
#include "code\game\objects\structures\stairs.dm"
|
||||
#include "code\game\objects\structures\syndicate_uplink_beacon.dm"
|
||||
#include "code\game\objects\structures\table_frames.dm"
|
||||
#include "code\game\objects\structures\tables_racks.dm"
|
||||
#include "code\game\objects\structures\tank_dispenser.dm"
|
||||
|
||||
@@ -35,6 +35,8 @@ type Info = {
|
||||
intro: string;
|
||||
code: string;
|
||||
failsafe_code: string;
|
||||
replacement_code: string;
|
||||
replacement_frequency: string;
|
||||
has_uplink: BooleanLike;
|
||||
uplink_intro: string;
|
||||
uplink_unlock_info: string;
|
||||
@@ -120,8 +122,15 @@ const EmployerSection = (props, context) => {
|
||||
|
||||
const UplinkSection = (props, context) => {
|
||||
const { data } = useBackend<Info>(context);
|
||||
const { has_uplink, uplink_intro, uplink_unlock_info, code, failsafe_code } =
|
||||
data;
|
||||
const {
|
||||
has_uplink,
|
||||
uplink_intro,
|
||||
uplink_unlock_info,
|
||||
code,
|
||||
failsafe_code,
|
||||
replacement_code,
|
||||
replacement_frequency,
|
||||
} = data;
|
||||
return (
|
||||
<Section title="Uplink" mb={!has_uplink && -1}>
|
||||
<Stack fill>
|
||||
@@ -149,6 +158,19 @@ const UplinkSection = (props, context) => {
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
<br />
|
||||
<Section textAlign="Center">
|
||||
If you lose your uplink, you can craft a Syndicate Uplink Beacon and
|
||||
then speak{' '}
|
||||
<span style={goalstyle}>
|
||||
<b>{replacement_code}</b>
|
||||
</span>{' '}
|
||||
on radio frequency{' '}
|
||||
<span style={goalstyle}>
|
||||
<b>{replacement_frequency}</b>
|
||||
</span>{' '}
|
||||
after synchronizing with the beacon.
|
||||
</Section>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user