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