diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm
index 9eace6f7c1d..3671dc34c62 100644
--- a/code/datums/uplink_item.dm
+++ b/code/datums/uplink_item.dm
@@ -560,7 +560,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/dangerous/syndieborg
name = "Syndicate Cyborg"
- desc = "A cyborg designed and programmed for systematic extermination of non-Syndicate personnel."
+ desc = "A cyborg designed and programmed for systematic extermination of non-Syndicate personnel. Comes in Assault, Medical, or Saboteur variants."
reference = "SC"
item = /obj/item/antag_spawner/borg_tele
refund_path = /obj/item/antag_spawner/borg_tele
diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm
index 7a25f4ece1b..2572f826735 100644
--- a/code/game/objects/items/devices/chameleonproj.dm
+++ b/code/game/objects/items/devices/chameleonproj.dm
@@ -148,3 +148,100 @@
/obj/effect/dummy/chameleon/Destroy()
master.disrupt(0)
return ..()
+
+/obj/item/borg_chameleon
+ name = "cyborg chameleon projector"
+ icon = 'icons/obj/device.dmi'
+ icon_state = "shield0"
+ item_state = "electronic"
+ w_class = WEIGHT_CLASS_SMALL
+ var/active = FALSE
+ var/activationCost = 300
+ var/activationUpkeep = 50
+ var/disguise = "landmate"
+ var/datum/component/mobhook // need this to deal with unregistration properly
+ var/mob/living/silicon/robot/syndicate/saboteur/user // needed for process()
+
+/obj/item/borg_chameleon/Destroy()
+ QDEL_NULL(mobhook)
+ return ..()
+
+/obj/item/borg_chameleon/dropped(mob/user)
+ . = ..()
+ disrupt(user)
+
+/obj/item/borg_chameleon/equipped(mob/user)
+ . = ..()
+ disrupt(user)
+
+/obj/item/borg_chameleon/attack_self(mob/living/silicon/robot/syndicate/saboteur/user)
+ if (user && user.cell && user.cell.charge > activationCost)
+ if (isturf(user.loc))
+ toggle(user)
+ else
+ to_chat(user, "You can't use [src] while inside something!")
+ else
+ to_chat(user, "You need at least [activationCost] charge in your cell to use [src]!")
+
+/obj/item/borg_chameleon/proc/toggle(mob/living/silicon/robot/syndicate/saboteur/user)
+ if(active)
+ playsound(src, 'sound/effects/pop.ogg', 100, 1, -6)
+ to_chat(user, "You deactivate \the [src].")
+ deactivate(user)
+ else
+ to_chat(user, "You activate \the [src].")
+ var/start = user.filters.len
+ var/X,Y,rsq,i,f
+ for(i=1, i<=7, ++i)
+ do
+ X = 60*rand() - 30
+ Y = 60*rand() - 30
+ rsq = X*X + Y*Y
+ while(rsq<100 || rsq>900)
+ user.filters += filter(type="wave", x=X, y=Y, size=rand()*2.5+0.5, offset=rand())
+ for(i=1, i<=7, ++i)
+ f = user.filters[start+i]
+ animate(f, offset=f:offset, time=0, loop=3, flags=ANIMATION_PARALLEL)
+ animate(offset=f:offset-1, time=rand()*20+10)
+ if (do_after(user, 50, target=user) && user.cell.use(activationCost))
+ playsound(src, 'sound/effects/bamf.ogg', 100, 1, -6)
+ to_chat(user, "You are now disguised as a Nanotrasen engineering cyborg.")
+ activate(user)
+ else
+ to_chat(user, "The chameleon field fizzles.")
+ do_sparks(3, FALSE, user)
+ for(i=1, i<=min(7, user.filters.len), ++i) // removing filters that are animating does nothing, we gotta stop the animations first
+ f = user.filters[start+i]
+ animate(f)
+ user.filters = null
+
+/obj/item/borg_chameleon/process()
+ if (user)
+ if (!user.cell || !user.cell.use(activationUpkeep))
+ disrupt(user)
+ else
+ return PROCESS_KILL
+
+/obj/item/borg_chameleon/proc/activate(mob/living/silicon/robot/syndicate/saboteur/user)
+ processing_objects.Add(src)
+ src.user = user
+ user.base_icon = disguise
+ user.icon_state = disguise
+ active = TRUE
+ user.active_proj = src
+ user.update_icons()
+
+/obj/item/borg_chameleon/proc/deactivate(mob/living/silicon/robot/syndicate/saboteur/user)
+ processing_objects.Remove(src)
+ QDEL_NULL(mobhook)
+ user.base_icon = initial(user.base_icon)
+ user.icon_state = initial(user.icon_state)
+ active = FALSE
+ user.active_proj = null
+ user.update_icons()
+ src.user = user
+
+/obj/item/borg_chameleon/proc/disrupt(mob/living/silicon/robot/syndicate/saboteur/user)
+ if(active)
+ to_chat(user, "Your chameleon field deactivates.")
+ deactivate(user)
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm
index e4624a00ba6..2bf94ff465a 100644
--- a/code/game/objects/items/weapons/RCD.dm
+++ b/code/game/objects/items/weapons/RCD.dm
@@ -456,20 +456,24 @@ GLOBAL_LIST_INIT(rcd_door_types, list(
/obj/item/rcd/proc/checkResource(amount, mob/user)
return matter >= amount
+/obj/item/rcd/borg
+ canRwall = 1
+ var/use_multiplier = 160
+
+/obj/item/rcd/borg/syndicate
+ use_multiplier = 80
+
/obj/item/rcd/borg/useResource(amount, mob/user)
if(!isrobot(user))
return 0
var/mob/living/silicon/robot/R = user
- return R.cell.use(amount * 160)
+ return R.cell.use(amount * use_multiplier)
/obj/item/rcd/borg/checkResource(amount, mob/user)
if(!isrobot(user))
return 0
var/mob/living/silicon/robot/R = user
- return R.cell.charge >= (amount * 160)
-
-/obj/item/rcd/borg
- canRwall = 1
+ return R.cell.charge >= (amount * use_multiplier)
/obj/item/rcd/proc/detonate_pulse()
audible_message("[src] begins to vibrate and \
diff --git a/code/modules/antagonists/_common/antag_spawner.dm b/code/modules/antagonists/_common/antag_spawner.dm
index 80a62f9c818..3ced0d5ceb0 100644
--- a/code/modules/antagonists/_common/antag_spawner.dm
+++ b/code/modules/antagonists/_common/antag_spawner.dm
@@ -19,7 +19,7 @@
var/checking = FALSE
var/TC_cost = 0
var/borg_to_spawn
- var/list/possible_types = list("Assault", "Medical")
+ var/list/possible_types = list("Assault", "Medical", "Saboteur")
/obj/item/antag_spawner/borg_tele/attack_self(mob/user)
if(used)
@@ -57,6 +57,8 @@
switch(borg_to_spawn)
if("Medical")
R = new /mob/living/silicon/robot/syndicate/medical(T)
+ else if("Saboteur")
+ R = new /mob/living/silicon/robot/syndicate/saboteur(T)
else
R = new /mob/living/silicon/robot/syndicate(T) //Assault borg by default
R.key = C.key
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 2f4056f6149..a546e299cd6 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -1293,61 +1293,6 @@ var/list/robot_verbs_default = list(
playsound(loc, 'sound/mecha/nominalsyndi.ogg', 75, 0)
-
-
-/mob/living/silicon/robot/syndicate
- base_icon = "syndie_bloodhound"
- icon_state = "syndie_bloodhound"
- lawupdate = 0
- scrambledcodes = 1
- pdahide = 1
- faction = list("syndicate")
- designation = "Syndicate Assault"
- modtype = "Syndicate"
- req_access = list(access_syndicate)
- ionpulse = 1
- magpulse = 1
- lawchannel = "State"
- var/playstyle_string = "You are a Syndicate assault cyborg!
\
- You are armed with powerful offensive tools to aid you in your mission: help the operatives secure the nuclear authentication disk. \
- Your cyborg LMG will slowly produce ammunition from your power supply, and your operative pinpointer will find and locate fellow nuclear operatives. \
- Help the operatives secure the disk at all costs!"
-
-/mob/living/silicon/robot/syndicate/New(loc)
- ..()
- cell.maxcharge = 25000
- cell.charge = 25000
-
-/mob/living/silicon/robot/syndicate/init()
- laws = new /datum/ai_laws/syndicate_override
- module = new /obj/item/robot_module/syndicate(src)
-
- aiCamera = new/obj/item/camera/siliconcam/robot_camera(src)
- radio = new /obj/item/radio/borg/syndicate(src)
- radio.recalculateChannels()
-
- spawn(5)
- if(playstyle_string)
- to_chat(src, playstyle_string)
-
- playsound(loc, 'sound/mecha/nominalsyndi.ogg', 75, 0)
-
-/mob/living/silicon/robot/syndicate/medical
- base_icon = "syndi-medi"
- icon_state = "syndi-medi"
- modtype = "Syndicate Medical"
- designation = "Syndicate Medical"
- playstyle_string = "You are a Syndicate medical cyborg!
\
- You are armed with powerful medical tools to aid you in your mission: help the operatives secure the nuclear authentication disk. \
- Your hypospray will produce Restorative Nanites, a wonder-drug that will heal most types of bodily damages, including clone and brain damage. It also produces morphine for offense. \
- Your defibrillator paddles can revive operatives through their hardsuits, or can be used on harm intent to shock enemies! \
- Your energy saw functions as a circular saw, but can be activated to deal more damage, and your operative pinpointer will find and locate fellow nuclear operatives. \
- Help the operatives secure the disk at all costs!"
-
-/mob/living/silicon/robot/syndicate/medical/init()
- ..()
- module = new /obj/item/robot_module/syndicate_medical(src)
-
/mob/living/silicon/robot/combat
base_icon = "droidcombat"
icon_state = "droidcombat"
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index c8a9f60290d..ee0cf0db06f 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -433,12 +433,9 @@
fix_modules()
/obj/item/robot_module/syndicate_saboteur
- name = "syndicate saboteur module"
+ name = "engineering robot module" //to disguise in examine
module_type = "Malf"
- module_actions = list(
- /datum/action/innate/robot_sight/meson,
- /datum/action/innate/robot_sight/thermal,
- )
+
stacktypes = list(
/obj/item/stack/sheet/metal/cyborg = 50,
/obj/item/stack/sheet/glass/cyborg = 50,
@@ -450,20 +447,22 @@
/obj/item/robot_module/syndicate_saboteur/New()
..()
- modules += new /obj/item/assembly/flash/cyborg(src)
- modules += new /obj/item/construction/rcd/borg/syndicate(src)
- modules += new /obj/item/pipe_dispenser(src)
+ modules += new /obj/item/rcd/borg/syndicate(src)
+ modules += new /obj/item/rpd(src)
modules += new /obj/item/extinguisher(src)
modules += new /obj/item/weldingtool/largetank/cyborg(src)
- modules += new /obj/item/screwdriver/nuke(src)
+ modules += new /obj/item/screwdriver/cyborg(src)
modules += new /obj/item/wrench/cyborg(src)
modules += new /obj/item/crowbar/cyborg(src)
modules += new /obj/item/wirecutters/cyborg(src)
modules += new /obj/item/multitool/cyborg(src)
- modules += new /obj/item/destTagger/borg(src)
- modules += new /obj/item/stack/cable_coil/cyborg(src)
- modules += new /obj/item/pinpointer/operative(src)
+ modules += new /obj/item/t_scanner(src)
+ modules += new /obj/item/analyzer(src)
+ modules += new /obj/item/gripper(src)
+ modules += new /obj/item/melee/energy/sword/cyborg(src)
+ modules += new /obj/item/card/emag(src)
modules += new /obj/item/borg_chameleon(src)
+ modules += new /obj/item/pinpointer/operative(src)
emag = null
for(var/T in stacktypes)
diff --git a/code/modules/mob/living/silicon/robot/syndicate.dm b/code/modules/mob/living/silicon/robot/syndicate.dm
new file mode 100644
index 00000000000..25cf1dd184d
--- /dev/null
+++ b/code/modules/mob/living/silicon/robot/syndicate.dm
@@ -0,0 +1,129 @@
+/mob/living/silicon/robot/syndicate
+ base_icon = "syndie_bloodhound"
+ icon_state = "syndie_bloodhound"
+ lawupdate = 0
+ scrambledcodes = 1
+ pdahide = 1
+ faction = list("syndicate")
+ designation = "Syndicate Assault"
+ modtype = "Syndicate"
+ req_access = list(access_syndicate)
+ ionpulse = 1
+ magpulse = 1
+ lawchannel = "State"
+ var/playstyle_string = "You are a Syndicate assault cyborg!
\
+ You are armed with powerful offensive tools to aid you in your mission: help the operatives secure the nuclear authentication disk. \
+ Your cyborg LMG will slowly produce ammunition from your power supply, and your operative pinpointer will find and locate fellow nuclear operatives. \
+ Help the operatives secure the disk at all costs!"
+
+/mob/living/silicon/robot/syndicate/New(loc)
+ ..()
+ cell.maxcharge = 25000
+ cell.charge = 25000
+
+/mob/living/silicon/robot/syndicate/init()
+ laws = new /datum/ai_laws/syndicate_override
+ module = new /obj/item/robot_module/syndicate(src)
+
+ aiCamera = new/obj/item/camera/siliconcam/robot_camera(src)
+ radio = new /obj/item/radio/borg/syndicate(src)
+ radio.recalculateChannels()
+
+ spawn(5)
+ if(playstyle_string)
+ to_chat(src, playstyle_string)
+
+ playsound(loc, 'sound/mecha/nominalsyndi.ogg', 75, 0)
+
+/mob/living/silicon/robot/syndicate/medical
+ base_icon = "syndi-medi"
+ icon_state = "syndi-medi"
+ modtype = "Syndicate Medical"
+ designation = "Syndicate Medical"
+ playstyle_string = "You are a Syndicate medical cyborg!
\
+ You are armed with powerful medical tools to aid you in your mission: help the operatives secure the nuclear authentication disk. \
+ Your hypospray will produce Restorative Nanites, a wonder-drug that will heal most types of bodily damages, including clone and brain damage. It also produces morphine for offense. \
+ Your defibrillator paddles can revive operatives through their hardsuits, or can be used on harm intent to shock enemies! \
+ Your energy saw functions as a circular saw, but can be activated to deal more damage, and your operative pinpointer will find and locate fellow nuclear operatives. \
+ Help the operatives secure the disk at all costs!"
+
+/mob/living/silicon/robot/syndicate/medical/init()
+ ..()
+ module = new /obj/item/robot_module/syndicate_medical(src)
+
+/mob/living/silicon/robot/syndicate/saboteur
+ base_icon = "syndi-engi"
+ icon_state = "syndi-engi"
+ modtype = "Syndicate Saboteur"
+ designation = "Syndicate Saboteur"
+ var/mail_destination = 0
+ var/obj/item/borg_chameleon/active_proj = null
+ playstyle_string = "You are a Syndicate saboteur cyborg!
\
+ You are equipped with robust engineering tools to aid you in your mission: help the operatives secure the nuclear authentication disk. \
+ Your destination tagger will allow you to stealthily traverse the disposal network across the station \
+ Your cyborg chameleon projector allows you to assume the appearance of a Nanotrasen engineering cyborg, and undertake covert actions on the station. \
+ You are able to hijack Nanotrasen cyborgs by emagging their internal components, make sure to flash them first. \
+ You are armed with a standard energy sword, use it to ambush key targets if needed.\
+ Be aware that taking damage or being touched will break your disguise. \
+ Help the operatives secure the disk at all costs!"
+
+/mob/living/silicon/robot/syndicate/saboteur/init()
+ ..()
+ module = new /obj/item/robot_module/syndicate_saboteur(src)
+
+/mob/living/silicon/robot/verb/modify_name()
+ set name = "Modify name"
+ set category = "Saboteur"
+ rename_self(braintype, 1)
+
+/mob/living/silicon/robot/syndicate/saboteur/verb/set_mail_tag()
+ set name = "Set mail tag"
+ set desc = "Tag yourself for delivery through the disposals system."
+ set category = "Saboteur"
+
+ var/tag = input("Select the desired destination.", "Set Mail Tag", null) as null|anything in GLOB.TAGGERLOCATIONS
+
+ if(!tag || GLOB.TAGGERLOCATIONS[tag])
+ mail_destination = 0
+ return
+
+ to_chat(src, "You configure your internal beacon, tagging yourself for delivery to '[tag]'.")
+ mail_destination = GLOB.TAGGERLOCATIONS.Find(tag)
+
+ //Auto flush if we use this verb inside a disposal chute.
+ var/obj/machinery/disposal/D = src.loc
+ if(istype(D))
+ to_chat(src, "\The [D] acknowledges your signal.")
+ D.flush_count = D.flush_every_ticks
+
+ return
+
+/mob/living/silicon/robot/syndicate/saboteur/attackby()
+ if(active_proj)
+ active_proj.disrupt(src)
+ ..()
+
+/mob/living/silicon/robot/syndicate/saboteur/attack_hand()
+ if(active_proj)
+ active_proj.disrupt(src)
+ ..()
+
+/mob/living/silicon/robot/syndicate/saboteur/ex_act()
+ if(active_proj)
+ active_proj.disrupt(src)
+ ..()
+
+/mob/living/silicon/robot/syndicate/saboteur/emp_act()
+ if(active_proj)
+ active_proj.disrupt(src)
+ ..()
+
+/mob/living/silicon/robot/syndicate/saboteur/bullet_act()
+ if(active_proj)
+ active_proj.disrupt(src)
+ ..()
+
+/mob/living/silicon/robot/syndicate/saboteur/attackby()
+ if(active_proj)
+ active_proj.disrupt(src)
+ ..()
diff --git a/icons/mob/robots.dmi b/icons/mob/robots.dmi
index d35638a6d19..eb59b0288b3 100644
Binary files a/icons/mob/robots.dmi and b/icons/mob/robots.dmi differ
diff --git a/paradise.dme b/paradise.dme
index f80ea688c86..45a4f96f7d7 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -1797,6 +1797,7 @@
#include "code\modules\mob\living\silicon\robot\robot_module_actions.dm"
#include "code\modules\mob\living\silicon\robot\robot_modules.dm"
#include "code\modules\mob\living\silicon\robot\robot_movement.dm"
+#include "code\modules\mob\living\silicon\robot\syndicate.dm"
#include "code\modules\mob\living\silicon\robot\update_status.dm"
#include "code\modules\mob\living\silicon\robot\drone\drone.dm"
#include "code\modules\mob\living\silicon\robot\drone\drone_abilities.dm"
@@ -2350,4 +2351,4 @@
#include "goon\code\datums\browserOutput.dm"
#include "interface\interface.dm"
#include "interface\skin.dmf"
-// END_INCLUDE
\ No newline at end of file
+// END_INCLUDE