diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index b177ac195906..54cd8b3c06e2 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -141,8 +141,8 @@ #define INIT_ORDER_VIS 80 #define INIT_ORDER_SECURITY_LEVEL 79 #define INIT_ORDER_MATERIALS 76 -#define INIT_ORDER_RESEARCH 75 -#define INIT_ORDER_STATION 74 +#define INIT_ORDER_STATION 75 +#define INIT_ORDER_RESEARCH 74 #define INIT_ORDER_QUIRKS 73 #define INIT_ORDER_EVENTS 70 #define INIT_ORDER_JOBS 65 diff --git a/code/controllers/subsystem/processing/quirks.dm b/code/controllers/subsystem/processing/quirks.dm index 07201a25e7fd..dd301aeb2a0b 100644 --- a/code/controllers/subsystem/processing/quirks.dm +++ b/code/controllers/subsystem/processing/quirks.dm @@ -17,13 +17,18 @@ PROCESSING_SUBSYSTEM_DEF(quirks) list("Ageusia","Vegetarian","Deviant Tastes"), list("Ananas Affinity","Ananas Aversion"), list("Alcohol Tolerance","Light Drinker"), - list("Prosthetic Limb (Left Arm)","Prosthetic Limb"), - list("Prosthetic Limb (Right Arm)","Prosthetic Limb"), - list("Prosthetic Limb (Left Leg)","Prosthetic Limb"), - list("Prosthetic Limb (Right Leg)","Prosthetic Limb"), - list("Prosthetic Limb (Left Leg)","Paraplegic"), - list("Prosthetic Limb (Right Leg)","Paraplegic"), - list("Prosthetic Limb","Paraplegic") + list("Prosthetic Limb (Left Arm)","Prosthetic Limb", "Body Purist"), + list("Prosthetic Limb (Right Arm)","Prosthetic Limb", "Body Purist"), + list("Prosthetic Limb (Left Leg)","Prosthetic Limb", "Body Purist"), + list("Prosthetic Limb (Right Leg)","Prosthetic Limb", "Body Purist"), + list("Prosthetic Limb (Left Leg)","Paraplegic", "Body Purist"), + list("Prosthetic Limb (Right Leg)","Paraplegic", "Body Purist"), + list("Prosthetic Limb", "Paraplegic"), + list("Prosthetic Limb", "Body Purist"), + list("Cybernetic Organ (Lungs)", "Body Purist"), + list("Cybernetic Organ (Heart)", "Body Purist"), + list("Cybernetic Organ (Liver)", "Body Purist"), + list("Upgraded Cybernetic Organ", "Body Purist") ) /datum/controller/subsystem/processing/quirks/Initialize(timeofday) diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm index 80e0fbf155aa..235606899e64 100644 --- a/code/datums/mood_events/generic_negative_events.dm +++ b/code/datums/mood_events/generic_negative_events.dm @@ -238,3 +238,9 @@ /datum/mood_event/surgery description = "HE'S CUTTING ME OPEN!!\n" mood_change = -8 + +/datum/mood_event/body_purist + description = span_warning("I feel cybernetics attached to me, and I HATE IT!") + +/datum/mood_event/body_purist/add_effects(power) + mood_change = power diff --git a/code/datums/station_traits/positive_traits.dm b/code/datums/station_traits/positive_traits.dm index 664372db8b69..2b0e8e2826c1 100644 --- a/code/datums/station_traits/positive_traits.dm +++ b/code/datums/station_traits/positive_traits.dm @@ -130,3 +130,75 @@ weight = 4 trait_to_give = STATION_TRAIT_SHUTTLE_SALE show_in_report = TRUE + +/datum/station_trait/cybernetic_revolution + name = "Cybernetic Revolution" + trait_type = STATION_TRAIT_POSITIVE + weight = 1 + show_in_report = TRUE + report_message = "The new trends in cybernetics have come to the station! Everyone has some form of cybernetic implant." + trait_to_give = STATION_TRAIT_CYBERNETIC_REVOLUTION + /// List of all job types with the cybernetics they should receive. + // Should be themed around their job/department. If no theme is possible, a basic cybernetic organ is fine. + var/static/list/job_to_cybernetic = list( + /datum/job/assistant = /obj/item/organ/heart/cybernetic, + /datum/job/artist = /obj/item/organ/heart/cybernetic, + /datum/job/atmos = /obj/item/organ/cyberimp/mouth/breathing_tube, // Inhaling gases. + /datum/job/bartender = /obj/item/organ/liver/cybernetic/upgraded, // Drinking their own drinks. + /datum/job/brigphysician = /obj/item/organ/cyberimp/eyes/hud/medical, + /datum/job/captain = /obj/item/organ/heart/cybernetic/upgraded, + /datum/job/cargo_tech = /obj/item/organ/stomach/cybernetic, + /datum/job/chaplain = /obj/item/organ/cyberimp/brain/anti_drop, // Preventing null rod loss. + /datum/job/chemist = /obj/item/organ/cyberimp/eyes/hud/science, // For seeing reagents. + /datum/job/chief_engineer = /obj/item/organ/cyberimp/chest/thrusters, + /datum/job/clerk = /obj/item/organ/stomach/cybernetic, + /datum/job/clown = /obj/item/organ/cyberimp/brain/anti_stun, // Funny. + /datum/job/cmo = /obj/item/organ/cyberimp/chest/reviver, + /datum/job/cook = /obj/item/organ/cyberimp/chest/nutriment/plus, + /datum/job/curator = /obj/item/organ/eyes/robotic/glow, // Spookie. + /datum/job/detective = /obj/item/organ/lungs/cybernetic/upgraded, // Smoker. + /datum/job/doctor = /obj/item/organ/cyberimp/arm/toolset/surgery, + /datum/job/engineer = /obj/item/organ/cyberimp/arm/toolset, + /datum/job/geneticist = /obj/item/organ/stomach/fly, + /datum/job/head_of_personnel = /obj/item/organ/eyes/robotic, + /datum/job/hos = /obj/item/organ/cyberimp/brain/anti_drop, + /datum/job/hydro = /obj/item/organ/cyberimp/chest/nutriment, + /datum/job/janitor = /obj/item/organ/heart/cybernetic, // ACTUAL x-ray eyes is likely "not balanced" and all alternatives suck. So boring heart. + /datum/job/lawyer = /obj/item/organ/heart/cybernetic/upgraded, + /datum/job/mime = /obj/item/organ/tongue/robot, // ... + /datum/job/mining = /obj/item/organ/cyberimp/chest/reviver, // Replace with a reusable mining-specific implant if one is added later. + /datum/job/miningmedic = /obj/item/organ/cyberimp/eyes/hud/medical, + /datum/job/network_admin = /obj/item/organ/cyberimp/arm/toolset, + /datum/job/officer = /obj/item/organ/cyberimp/arm/flash, + /datum/job/paramedic = /obj/item/organ/cyberimp/eyes/hud/medical, + /datum/job/psych = /obj/item/organ/ears/cybernetic, + /datum/job/qm = /obj/item/organ/stomach/cybernetic, + /datum/job/rd = /obj/item/organ/cyberimp/eyes/hud/diagnostic, // Replace with a very cool science implant if one is added later. + /datum/job/roboticist = /obj/item/organ/cyberimp/eyes/hud/diagnostic, // Robots and mechs. + /datum/job/scientist = /obj/item/organ/cyberimp/eyes/hud/science, // Science, duh. + /datum/job/tourist = /obj/item/organ/heart/cybernetic, + /datum/job/virologist = /obj/item/organ/lungs/cybernetic/upgraded, + /datum/job/warden = /obj/item/organ/cyberimp/eyes/hud/security, + ) + +/datum/station_trait/cybernetic_revolution/New() + . = ..() + RegisterSignal(SSdcs, COMSIG_GLOB_JOB_AFTER_SPAWN, PROC_REF(on_job_after_spawn)) + +/datum/station_trait/cybernetic_revolution/proc/on_job_after_spawn(datum/source, datum/job/job, mob/living/living_mob, mob/new_player_mob, joined_late) + // Having the Body Purist quirk prevents the effects of this station trait from being applied to you. + var/datum/quirk/body_purist/body_purist = /datum/quirk/body_purist + if(initial(body_purist.name) in new_player_mob.client.prefs.all_quirks) + return + + var/cybernetic_type = job_to_cybernetic[job.type] + if(cybernetic_type) + var/obj/item/organ/cybernetic = new cybernetic_type() + // Timer is needed because doing it immediately doesn't REPLACE organs for some unknown reason, so got to do it next tick or whatever. + addtimer(CALLBACK(cybernetic, TYPE_PROC_REF(/obj/item/organ, Insert), living_mob), 1) + return + + if(isAI(living_mob)) + var/mob/living/silicon/ai/ai = living_mob + ai.eyeobj.relay_speech = TRUE + return diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm index 60112254cb50..f52dab508442 100644 --- a/code/datums/traits/negative.dm +++ b/code/datums/traits/negative.dm @@ -833,3 +833,71 @@ if(disallowed_trait) return "You have no DNA!" return FALSE + +/datum/quirk/body_purist + name = "Body Purist" + desc = "You believe your body is a temple and its natural form is an embodiment of perfection. Accordingly, you despise the idea of ever augmenting it with unnatural parts, cybernetic, prosthetic, or anything like it." + icon = "person-rays" + value = -2 + mood_quirk = TRUE + gain_text = span_danger("You now begin to hate the idea of having cybernetic implants.") + lose_text = span_notice("Maybe cybernetics aren't so bad. You now feel okay with augmentations and prosthetics.") + medical_record_text = "This patient has disclosed an extreme hatred for unnatural bodyparts and augmentations." + var/cybernetics_level = 0 + +/datum/quirk/body_purist/add() + check_cybernetics() + RegisterSignal(quirk_holder, COMSIG_CARBON_GAIN_ORGAN, PROC_REF(on_organ_gain)) + RegisterSignal(quirk_holder, COMSIG_CARBON_LOSE_ORGAN, PROC_REF(on_organ_lose)) + RegisterSignal(quirk_holder, COMSIG_CARBON_ATTACH_LIMB, PROC_REF(on_limb_gain)) + RegisterSignal(quirk_holder, COMSIG_CARBON_REMOVE_LIMB, PROC_REF(on_limb_lose)) + +/datum/quirk/body_purist/remove() + UnregisterSignal(quirk_holder, list( + COMSIG_CARBON_GAIN_ORGAN, + COMSIG_CARBON_LOSE_ORGAN, + COMSIG_CARBON_ATTACH_LIMB, + COMSIG_CARBON_REMOVE_LIMB, + )) + SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "body_purist") + +/datum/quirk/body_purist/proc/check_cybernetics() + var/mob/living/carbon/owner = quirk_holder + if(!istype(owner)) + return + for(var/obj/item/bodypart/limb as anything in owner.bodyparts) + if(!limb.is_organic_limb()) + cybernetics_level++ + for(var/obj/item/organ/organ as anything in owner.internal_organs) + if(organ.organ_flags & ORGAN_SYNTHETIC || organ.status == ORGAN_ROBOTIC) + cybernetics_level++ + update_mood() + +/datum/quirk/body_purist/proc/update_mood() + SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "body_purist") + if(cybernetics_level) + SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "body_purist", /datum/mood_event/body_purist, -cybernetics_level * 10) + +/datum/quirk/body_purist/proc/on_organ_gain(datum/source, obj/item/organ/new_organ, special) + SIGNAL_HANDLER + if(new_organ.organ_flags & ORGAN_SYNTHETIC || new_organ.status == ORGAN_ROBOTIC) + cybernetics_level++ + update_mood() + +/datum/quirk/body_purist/proc/on_organ_lose(datum/source, obj/item/organ/old_organ, special) + SIGNAL_HANDLER + if(old_organ.organ_flags & ORGAN_SYNTHETIC || old_organ.status == ORGAN_ROBOTIC) + cybernetics_level-- + update_mood() + +/datum/quirk/body_purist/proc/on_limb_gain(datum/source, obj/item/bodypart/new_limb, special) + SIGNAL_HANDLER + if(!new_limb.is_organic_limb()) + cybernetics_level++ + update_mood() + +/datum/quirk/body_purist/proc/on_limb_lose(datum/source, obj/item/bodypart/old_limb, special) + SIGNAL_HANDLER + if(!old_limb.is_organic_limb()) + cybernetics_level-- + update_mood() diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index a25b24477017..326707ee031c 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -531,6 +531,11 @@ design_ids = list("cybernetic_heart", "cybernetic_liver", "cybernetic_lungs", "cybernetic_stomach", "cybernetic_ears", "cybernetic_appendix") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) +datum/techweb_node/cyber_organs/New() + ..() + if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 500) + /datum/techweb_node/cyber_organs_upgraded id = "cyber_organs_upgraded" display_name = "Upgraded Cybernetic Organs" @@ -539,6 +544,11 @@ design_ids = list("cybernetic_heart_u", "cybernetic_liver_u", "cybernetic_lungs_u", "cybernetic_stomach_u") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) +/datum/techweb_node/cyber_organs_upgraded/New() + ..() + if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 750) + /datum/techweb_node/ipc_organs id = "ipc_organs" display_name = "IPC Parts" @@ -555,6 +565,11 @@ design_ids = list("ci-nutriment", "ci-breather", "ci-gloweyes", "ci-meson", "ci-welding", "ci-medhud", "ci-sechud", "ci-scihud", "ci-diaghud") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) +/datum/techweb_node/cyber_implants/New() + ..() + if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1250) + /datum/techweb_node/adv_cyber_implants id = "adv_cyber_implants" display_name = "Advanced Cybernetic Implants" @@ -563,6 +578,11 @@ design_ids = list("ci-toolset", "ci-surgery", "ci-reviver", "ci-nutrimentplus", "ci-magboots") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) +/datum/techweb_node/adv_cyber_implants/New() + ..() + if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1250) + /datum/techweb_node/combat_cyber_implants id = "combat_cyber_implants" display_name = "Combat Cybernetic Implants" @@ -571,6 +591,11 @@ design_ids = list("ci-antidrop", "ci-antistun", "ci-thrusters", "ci-jumpboots", "ci-wheelies") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) +/datum/techweb_node/combat_cyber_implants/New() + ..() + if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1250) + /datum/techweb_node/illegal_cyber_implants id = "illegal_cyber_implants" display_name = "Illegal Cybernetic Implants" @@ -579,6 +604,11 @@ design_ids = list("ci-noslipwater") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) +/datum/techweb_node/illegal_cyber_implants/New() + ..() + if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + ////////////////////////Tools//////////////////////// /datum/techweb_node/basic_mining diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index bff21e812db6..faa883436485 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -324,6 +324,7 @@ /obj/item/bodypart/proc/attach_limb(mob/living/carbon/C, special) moveToNullspace() set_owner(C) + SEND_SIGNAL(C, COMSIG_CARBON_ATTACH_LIMB, src, special) C.bodyparts += src if(held_index) if(held_index > C.hand_bodyparts.len) diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index e4cfbbe821f0..952fbefb65fe 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -57,6 +57,7 @@ for(var/X in actions) var/datum/action/A = X A.Grant(M) + SEND_SIGNAL(M, COMSIG_CARBON_GAIN_ORGAN, src, special) //Special is for instant replacement like autosurgeons /obj/item/organ/proc/Remove(mob/living/carbon/M, special = FALSE) @@ -70,7 +71,7 @@ for(var/X in actions) var/datum/action/A = X A.Remove(M) - + SEND_SIGNAL(M, COMSIG_CARBON_LOSE_ORGAN, src, special) /obj/item/organ/proc/on_find(mob/living/finder) return diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index 15eadfe6557e..8b1a6e8f7ddd 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -84,6 +84,7 @@ #include "reagent_recipe_collisions.dm" #include "spawn_humans.dm" #include "species_whitelists.dm" +#include "station_trait_tests.dm" #include "subsystem_init.dm" #include "timer_sanity.dm" #include "trait_addition_and_removal.dm" diff --git a/code/modules/unit_tests/station_trait_tests.dm b/code/modules/unit_tests/station_trait_tests.dm new file mode 100644 index 000000000000..19d5f6a76860 --- /dev/null +++ b/code/modules/unit_tests/station_trait_tests.dm @@ -0,0 +1,10 @@ +/// This test spawns various station traits and looks through them to see if there's any errors. +/datum/unit_test/station_traits + +/datum/unit_test/station_traits/Run() + var/datum/station_trait/cybernetic_revolution/cyber_trait = allocate(/datum/station_trait/cybernetic_revolution) + for(var/datum/job/job in subtypesof(/datum/job)) + if(!(initial(job.faction) || job.faction != "Station")) // Replace with job types if it gets ported. + continue + if(!(job in cyber_trait.job_to_cybernetic)) + Fail("Job [job] does not have an assigned cybernetic for [cyber_trait.type] station trait.") diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index f18e4c916eaa..6e192f888d24 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -833,6 +833,11 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) Loaded with bullets which release micro-electromagnetic pulses on hit, disrupting electronics on the target hit." item = /obj/item/ammo_box/magazine/m10mm/emp +/datum/uplink_item/ammo/pistol/emp/New() + ..() + if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) + cost *= 3 + /datum/uplink_item/ammo/shotgun cost = 2 include_modes = list(/datum/game_mode/nuclear) @@ -1241,6 +1246,11 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) cost = 2 manufacturer = /datum/corporation/traitor/cybersun +/datum/uplink_item/explosives/emp/New() + ..() + if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) + cost *= 3 + /datum/uplink_item/explosives/ducky name = "Exploding Rubber Duck" desc = "A seemingly innocent rubber duck. When placed, it arms, and will violently explode when stepped on." @@ -1312,6 +1322,11 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/sbeacondrop/emp cost = 7 +/datum/uplink_item/explosives/syndicate_bomb/emp/New() + ..() + if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) + cost *= 2 + /datum/uplink_item/explosives/syndicate_detonator name = "Syndicate Detonator" desc = "The Syndicate detonator is a companion device to the Syndicate bomb. Simply press the included button \ @@ -1561,6 +1576,11 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) manufacturer = /datum/corporation/traitor/donkco surplus = 30 +/datum/uplink_item/stealthy_tools/emplight/New() + ..() + if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) + cost *= 3 + /datum/uplink_item/stealthy_tools/mulligan name = "Mulligan" desc = "Screwed up and have security on your tail? This handy syringe will give you a completely new identity \ @@ -1846,6 +1866,11 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) cost = 4 exclude_modes = list(/datum/game_mode/nuclear) //Buy your own ammo you lazy sods +/datum/uplink_item/device_tools/illegal_ammo_disk/New() + ..() + if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) + cost *= 3 // Can print EMP. + /datum/uplink_item/device_tools/medgun name = "Medbeam Gun" desc = "A wonder of Syndicate engineering, the Medbeam gun, or Medi-Gun enables a medic to keep his fellow \ @@ -2091,6 +2116,13 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) category = "Implants" surplus = 50 + +/datum/uplink_item/implants/New() + ..() + if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) + // All implants are half off and can be as low as one TC. + cost = max(1, ROUND_UP(cost/2)) + /datum/uplink_item/implants/reusable name = "Reusable Autosurgeon" desc = "An empty autosurgeon, but unlike others can be used multiple times. More suspicious than others." @@ -2228,7 +2260,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) desc = "A modified version of the Stechkin pistol placed inside of the forearm to allow for easy concealment." item = /obj/item/autosurgeon/arm/syndicate/stechkin_implant cost = 9 - + /datum/uplink_item/implants/noslipall name = "Slip Prevention Implant" desc = "An implant that uses advanced sensors to detect when you are slipping and utilize motors in order to prevent it." @@ -2352,6 +2384,11 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/autosurgeon/arm/syndicate/syndie_hammer restricted_species = list("preternis") +/datum/uplink_item/race_restricted/hammerimplant/New() + ..() + if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) + cost = max(1, ROUND_UP(cost/2)) + /datum/uplink_item/race_restricted/killertomatos name = "Killer Tomatoes" desc = "The Syndicates local gardeners brewed these up for our plant comrades (does not work against fellow plants)." @@ -2433,6 +2470,12 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) cost = 8 manufacturer = /datum/corporation/traitor/vahlen +/datum/uplink_item/role_restricted/arm_medical_gun/New() + ..() + if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) + // All implants are half off (rounded) and can be as low as one TC. + cost = max(1, ROUND_UP(cost/2)) + /datum/uplink_item/role_restricted/brainwash_disk name = "Brainwashing Surgery Program" desc = "A disk containing the procedure to perform a brainwashing surgery, allowing you to implant an objective onto a target. \