diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm
index 020017c3fe..003f02cda7 100644
--- a/_maps/map_files/generic/CentCom.dmm
+++ b/_maps/map_files/generic/CentCom.dmm
@@ -16621,9 +16621,7 @@
/turf/open/floor/grass,
/area/centcom/holding)
"Ms" = (
-/obj/effect/mob_spawn/human/ghostcafe{
- dir = 8
- },
+/obj/effect/mob_spawn/human/ghostcafe,
/turf/open/indestructible/hotelwood,
/area/centcom/holding)
"Mt" = (
@@ -18702,6 +18700,10 @@
},
/turf/open/floor/plasteel,
/area/syndicate_mothership)
+"XJ" = (
+/obj/effect/mob_spawn/robot/ghostcafe,
+/turf/open/indestructible/hotelwood,
+/area/centcom/holding)
"XL" = (
/obj/machinery/door/airlock/wood,
/turf/open/floor/wood,
@@ -48091,7 +48093,7 @@ Sd
GY
NT
Tw
-Ms
+Sd
Ro
NT
vt
@@ -48347,9 +48349,9 @@ Nd
Nd
Nd
Nd
-Nd
-Nd
-Nd
+Ms
+Sd
+XJ
Nd
Nd
Nd
@@ -48603,10 +48605,10 @@ aa
aa
aa
aa
-aa
-aa
-aa
-aa
+Nd
+Nd
+Nd
+Nd
Nd
vv
VA
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index 80fd177d84..7225c776c4 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -547,6 +547,7 @@
desc = "A cyborg resizer, it makes a cyborg huge."
icon_state = "cyborg_upgrade3"
+/* moved to sandcode
/obj/item/borg/upgrade/expand/action(mob/living/silicon/robot/R, user = usr)
. = ..()
if(.)
@@ -573,6 +574,7 @@
R.resize = 2
R.hasExpanded = TRUE
R.update_transform()
+*/
/obj/item/borg/upgrade/expand/deactivate(mob/living/silicon/robot/R, user = usr)
. = ..()
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index 8c12d747d5..101334cd7f 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -92,7 +92,7 @@
return new storage_type(src)
-/obj/item/robot_module/proc/add_module(obj/item/I, nonstandard, requires_rebuild)
+/* /obj/item/robot_module/proc/add_module(obj/item/I, nonstandard, requires_rebuild)
rad_flags |= RAD_NO_CONTAMINATE
if(istype(I, /obj/item/stack))
var/obj/item/stack/S = I
@@ -141,6 +141,7 @@
if(requires_rebuild)
rebuild_modules()
return I
+*/ //replaced by the one in sandcode
//Adds flavoursome dogborg items to dogborg variants without mechanical benefits
/obj/item/robot_module/proc/dogborg_equip()
@@ -310,8 +311,7 @@
/obj/item/t_scanner/adv_mining_scanner,
/obj/item/restraints/handcuffs/cable/zipties,
/obj/item/soap/nanotrasen,
- /obj/item/borg/cyborghug,
- /obj/item/dildo/cyborg)
+ /obj/item/borg/cyborghug)
emag_modules = list(/obj/item/melee/transforming/energy/sword/cyborg)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg,
@@ -346,8 +346,7 @@
/obj/item/organ_storage,
/obj/item/borg/lollipop,
/obj/item/sensor_device,
- /obj/item/shockpaddles/cyborg,
- /obj/item/dildo/cyborg)
+ /obj/item/shockpaddles/cyborg)
emag_modules = list(/obj/item/reagent_containers/borghypo/hacked)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/medical,
@@ -468,8 +467,7 @@
/obj/item/stack/sheet/rglass/cyborg,
/obj/item/stack/rods/cyborg,
/obj/item/stack/tile/plasteel/cyborg,
- /obj/item/stack/cable_coil/cyborg,
- /obj/item/dildo/cyborg)
+ /obj/item/stack/cable_coil/cyborg)
emag_modules = list(/obj/item/borg/stun)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/engineer,
@@ -570,8 +568,7 @@
/obj/item/melee/baton/loaded,
/obj/item/gun/energy/disabler/cyborg,
/obj/item/clothing/mask/gas/sechailer/cyborg,
- /obj/item/pinpointer/crew,
- /obj/item/dildo/cyborg)
+ /obj/item/pinpointer/crew)
emag_modules = list(/obj/item/gun/energy/laser/cyborg)
ratvar_modules = list(/obj/item/clockwork/slab/cyborg/security,
/obj/item/clockwork/weapon/ratvarian_spear)
@@ -681,8 +678,7 @@
/obj/item/holosign_creator/cyborg,
/obj/item/borg/cyborghug/peacekeeper,
/obj/item/megaphone,
- /obj/item/borg/projectile_dampen,
- /obj/item/dildo/cyborg)
+ /obj/item/borg/projectile_dampen)
emag_modules = list(/obj/item/reagent_containers/borghypo/peace/hacked)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/peacekeeper,
@@ -820,8 +816,7 @@
/obj/item/mop/cyborg,
/obj/item/lightreplacer/cyborg,
/obj/item/holosign_creator,
- /obj/item/reagent_containers/spray/cyborg_drying,
- /obj/item/dildo/cyborg)
+ /obj/item/reagent_containers/spray/cyborg_drying)
emag_modules = list(/obj/item/reagent_containers/borghypo/borgshaker/hacked)
ratvar_modules = list(/obj/item/clockwork/slab/cyborg/service,
/obj/item/borg/sight/xray/truesight_lens)
@@ -964,8 +959,7 @@
/obj/item/cyborg_clamp,
/obj/item/stack/marker_beacon,
/obj/item/destTagger,
- /obj/item/stack/packageWrap,
- /obj/item/dildo/cyborg)
+ /obj/item/stack/packageWrap)
emag_modules = list(/obj/item/borg/stun)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/miner,
@@ -1051,8 +1045,7 @@
/obj/item/gun/ballistic/revolver/grenadelauncher/cyborg,
/obj/item/card/emag,
/obj/item/crowbar/cyborg,
- /obj/item/pinpointer/syndicate_cyborg,
- /obj/item/dildo/cyborg)
+ /obj/item/pinpointer/syndicate_cyborg)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/security,
@@ -1094,8 +1087,7 @@
/obj/item/pinpointer/syndicate_cyborg,
/obj/item/stack/medical/gauze/cyborg,
/obj/item/gun/medbeam,
- /obj/item/organ_storage,
- /obj/item/dildo/cyborg)
+ /obj/item/organ_storage)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/medical,
/obj/item/clockwork/weapon/ratvarian_spear)
@@ -1130,8 +1122,7 @@
/obj/item/destTagger/borg,
/obj/item/stack/cable_coil/cyborg,
/obj/item/pinpointer/syndicate_cyborg,
- /obj/item/borg_chameleon,
- /obj/item/dildo/cyborg)
+ /obj/item/borg_chameleon)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/engineer,
diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm
index 4efcad97ba..b863db4e46 100644
--- a/code/modules/research/designs/mechfabricator_designs.dm
+++ b/code/modules/research/designs/mechfabricator_designs.dm
@@ -796,6 +796,7 @@
construction_time = 120
category = list("Cyborg Upgrade Modules")
+/* moved to sandcode
/datum/design/borg_upgrade_expand
name = "Cyborg Upgrade (Expand)"
id = "borg_upgrade_expand"
@@ -804,6 +805,7 @@
materials = list(/datum/material/iron=200000, /datum/material/titanium=5000)
construction_time = 120
category = list("Cyborg Upgrade Modules")
+*/
/datum/design/boris_ai_controller
name = "B.O.R.I.S. AI-Cyborg Remote Control Module"
diff --git a/sandcode/code/datums/ai_laws.dm b/sandcode/code/datums/ai_laws.dm
new file mode 100644
index 0000000000..4ced25e2e4
--- /dev/null
+++ b/sandcode/code/datums/ai_laws.dm
@@ -0,0 +1,5 @@
+/datum/ai_laws/roleplay
+ name = "Roleplay"
+ id = "roleplay"
+ zeroth = "Roleplay as you'd like!"
+ inherent = list()
diff --git a/sandcode/code/game/objects/items/borg_shapeshifter.dm b/sandcode/code/game/objects/items/borg_shapeshifter.dm
new file mode 100644
index 0000000000..daa5850fc2
--- /dev/null
+++ b/sandcode/code/game/objects/items/borg_shapeshifter.dm
@@ -0,0 +1,669 @@
+/obj/item/borg_shapeshifter
+ name = "cyborg chameleon projector"
+ icon = 'icons/obj/device.dmi'
+ icon_state = "shield0"
+ flags_1 = CONDUCT_1
+ item_flags = NOBLUDGEON
+ item_state = "electronic"
+ lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
+ w_class = WEIGHT_CLASS_SMALL
+ var/friendlyName
+ var/savedName
+ var/savedIcon
+ var/savedBubbleIcon
+ var/savedOverride
+ var/savedPixelOffset
+ var/savedModuleName
+ var/active = FALSE
+ var/activationCost = 150
+ var/activationUpkeep = 5
+ var/disguise = null
+ var/disguise_icon_override = null
+ var/disguise_pixel_offset = null
+ var/disguise_dogborg = FALSE
+ var/mob/listeningTo
+ var/list/signalCache = list( // list here all signals that should break the camouflage
+ COMSIG_PARENT_ATTACKBY,
+ COMSIG_ATOM_ATTACK_HAND,
+ COMSIG_MOVABLE_IMPACT_ZONE,
+ COMSIG_ATOM_BULLET_ACT,
+ COMSIG_ATOM_EX_ACT,
+ COMSIG_ATOM_FIRE_ACT,
+ COMSIG_ATOM_EMP_ACT,
+ )
+ var/mob/living/silicon/robot/user // needed for process()
+ var/animation_playing = FALSE
+ var/list/borgmodels = list(
+ "(Standard) Default",
+ "(Standard) Heavy",
+ "(Standard) Sleek",
+ "(Standard) Marina",
+ "(Standard) Robot",
+ "(Standard) Eyebot",
+ "(Medical) Default",
+ "(Medical) Heavy",
+ "(Medical) Sleek",
+ "(Medical) Marina",
+ "(Medical) Droid",
+ "(Medical) Eyebot",
+ "(Medical) Medihound",
+ "(Medical) Medihound Dark",
+ "(Medical) Vale",
+ "(Engineering) Default",
+ "(Engineering) Default - Treads",
+ "(Engineering) Loader",
+ "(Engineering) Handy",
+ "(Engineering) Sleek",
+ "(Engineering) Can",
+ "(Engineering) Marina",
+ "(Engineering) Spider",
+ "(Engineering) Heavy",
+ "(Miner) Lavaland",
+ "(Miner) Asteroid",
+ "(Miner) Droid",
+ "(Miner) Sleek",
+ "(Miner) Marina",
+ "(Miner) Can",
+ "(Miner) Heavy",
+ "(Service) Waitress",
+ "(Service) Butler",
+ "(Service) Bro",
+ "(Service) Can",
+ "(Service) Tophat",
+ "(Service) Sleek",
+ "(Service) Heavy",
+ "(Janitor) Default",
+ "(Janitor) Marina",
+ "(Janitor) Sleek",
+ "(Janitor) Can")
+
+/obj/item/borg_shapeshifter/Initialize()
+ . = ..()
+ friendlyName = pick(GLOB.ai_names)
+
+/obj/item/borg_shapeshifter/Destroy()
+ return ..()
+
+/obj/item/borg_shapeshifter/dropped(mob/user)
+ . = ..()
+ disrupt(user)
+
+/obj/item/borg_shapeshifter/equipped(mob/user)
+ . = ..()
+ disrupt(user)
+
+/**
+ * check_menu: Checks if we are allowed to interact with a radial menu
+ *
+ * Arguments:
+ * * user The mob interacting with a menu
+ */
+/obj/item/borg_shapeshifter/proc/check_menu(mob/user)
+ if(!istype(user))
+ return FALSE
+ if(user.incapacitated() || !user.Adjacent(src))
+ return FALSE
+ return TRUE
+
+/obj/item/borg_shapeshifter/attack_self(mob/living/silicon/robot/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_shapeshifter/proc/toggle(mob/living/silicon/robot/user)
+ if(active)
+ playsound(src, 'sound/effects/pop.ogg', 100, TRUE, -6)
+ to_chat(user, "You deactivate \the [src].")
+ deactivate(user)
+ else
+ if(animation_playing)
+ to_chat(user, "\the [src] is recharging.")
+ return
+ var/mob/living/silicon/robot/R = loc
+ var/static/list/module_icons = sortList(list(
+ "Standard" = image(icon = 'icons/mob/robots.dmi', icon_state = "robot"),
+ "Medical" = image(icon = 'icons/mob/robots.dmi', icon_state = "medical"),
+ "Engineer" = image(icon = 'icons/mob/robots.dmi', icon_state = "engineer"),
+ "Security" = image(icon = 'icons/mob/robots.dmi', icon_state = "sec"),
+ "Service" = image(icon = 'icons/mob/robots.dmi', icon_state = "service_f"),
+ "Miner" = image(icon = 'icons/mob/robots.dmi', icon_state = "miner"),
+ "Peacekeeper" = image(icon = 'icons/mob/robots.dmi', icon_state = "peace"),
+ "Clown" = image(icon = 'icons/mob/robots.dmi', icon_state = "clown"),
+ "Syndicate" = image(icon = 'icons/mob/robots.dmi', icon_state = "synd_sec")
+ ))
+ var/module_selection = show_radial_menu(R, R , module_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
+ if(!module_selection)
+ return FALSE
+
+ switch(module_selection)
+ if("Standard")
+ var/static/list/standard_icons = sortList(list(
+ "Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "robot")
+ ))
+ var/borg_icon = show_radial_menu(R, R , standard_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
+ if(!borg_icon)
+ return FALSE
+ switch(borg_icon)
+ if("Default")
+ disguise = "robot"
+ disguise_icon_override = 'icons/mob/robots.dmi'
+ else
+ return FALSE
+
+ if("Medical")
+ var/static/list/med_icons = list(
+ "Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "medical"),
+ "Droid" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "medical"),
+ "Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekmed"),
+ "Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinamed"),
+ "Eyebot" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "eyebotmed"),
+ "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavymed"),
+ "Drake" = image(icon = 'sandcode/icons/mob/cyborg/drakemech.dmi', icon_state = "drakemedbox")
+ )
+ var/list/L = list("Medihound" = "medihound", "Medihound Dark" = "medihounddark", "Vale" = "valemed")
+ for(var/a in L)
+ var/image/wide = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = L[a])
+ wide.pixel_x = -16
+ med_icons[a] = wide
+ med_icons = sortList(med_icons)
+ var/borg_icon = show_radial_menu(R, R , med_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
+ if(!borg_icon)
+ return FALSE
+ switch(borg_icon)
+ if("Default")
+ disguise = "medical"
+ disguise_icon_override = 'icons/mob/robots.dmi'
+ if("Droid")
+ disguise = "medical"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Sleek")
+ disguise = "sleekmed"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Marina")
+ disguise = "marinamed"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Eyebot")
+ disguise = "eyebotmed"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Heavy")
+ disguise = "heavymed"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Medihound")
+ disguise = "medihound"
+ disguise_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
+ disguise_pixel_offset = -16
+ disguise_dogborg = TRUE
+ if("Medihound Dark")
+ disguise = "medihounddark"
+ disguise_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
+ disguise_pixel_offset = -16
+ disguise_dogborg = TRUE
+ if("Vale")
+ disguise = "valemed"
+ disguise_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
+ disguise_pixel_offset = -16
+ disguise_dogborg = TRUE
+ if("Drake")
+ disguise = "drakemed"
+ disguise_icon_override = 'sandcode/icons/mob/cyborg/drakemech.dmi'
+ disguise_pixel_offset = -16
+ disguise_dogborg = TRUE
+ else
+ return FALSE
+
+ if("Engineer")
+ var/static/list/engi_icons = list(
+ "Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "engineer"),
+ "Default - Treads" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "engi-tread"),
+ "Loader" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "loaderborg"),
+ "Handy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "handyeng"),
+ "Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekeng"),
+ "Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "caneng"),
+ "Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinaeng"),
+ "Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "spidereng"),
+ "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyeng"),
+ "Drake" = image(icon = 'sandcode/icons/mob/cyborg/drakemech.dmi', icon_state = "drakeengbox")
+ )
+ var/list/L = list("Pup Dozer" = "pupdozer", "Vale" = "valeeng")
+ for(var/a in L)
+ var/image/wide = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = L[a])
+ wide.pixel_x = -16
+ engi_icons[a] = wide
+ engi_icons = sortList(engi_icons)
+ var/borg_icon = show_radial_menu(R, R , engi_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
+ if(!borg_icon)
+ return FALSE
+ switch(borg_icon)
+ if("Default")
+ disguise = "engineer"
+ disguise_icon_override = 'icons/mob/robots.dmi'
+ if("Default - Treads")
+ disguise = "engi-tread"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Loader")
+ disguise = "loaderborg"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Handy")
+ disguise = "handyeng"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Sleek")
+ disguise = "sleekeng"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Can")
+ disguise = "caneng"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Marina")
+ disguise = "marinaeng"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Spider")
+ disguise = "spidereng"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Heavy")
+ disguise = "heavyeng"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Pup Dozer")
+ disguise = "pupdozer"
+ disguise_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
+ disguise_pixel_offset = -16
+ disguise_dogborg = TRUE
+ if("Vale")
+ disguise = "valeeng"
+ disguise_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
+ disguise_pixel_offset = -16
+ disguise_dogborg = TRUE
+ if("Alina")
+ disguise = "alina-eng"
+ disguise_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
+ disguise_pixel_offset = -16
+ disguise_dogborg = TRUE
+ if("Drake")
+ disguise = "drakeeng"
+ disguise_icon_override = 'sandcode/icons/mob/cyborg/drakemech.dmi'
+ disguise_pixel_offset = -16
+ disguise_dogborg = TRUE
+ else
+ return FALSE
+ if("Security")
+ var/static/list/sec_icons = list(
+ "Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "sec"),
+ "Default - Treads" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sec-tread"),
+ "Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleeksec"),
+ "Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "cansec"),
+ "Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinasec"),
+ "Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "spidersec"),
+ "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavysec"),
+ "Drake" = image(icon = 'sandcode/icons/mob/cyborg/drakemech.dmi', icon_state = "drakesecbox")
+ )
+ var/list/L = list("K9" = "k9", "Vale" = "valesec", "K9 Dark" = "k9dark")
+ for(var/a in L)
+ var/image/wide = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = L[a])
+ wide.pixel_x = -16
+ sec_icons[a] = wide
+ sec_icons = sortList(sec_icons)
+ var/borg_icon = show_radial_menu(R, R , sec_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
+ if(!borg_icon)
+ return FALSE
+ switch(borg_icon)
+ if("Default")
+ disguise = "sec"
+ disguise_icon_override = 'icons/mob/robots.dmi'
+ if("Default - Treads")
+ disguise = "sec-tread"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Sleek")
+ disguise = "sleeksec"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Marina")
+ disguise = "marinasec"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Can")
+ disguise = "cansec"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Spider")
+ disguise = "spidersec"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Heavy")
+ disguise = "heavysec"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("K9")
+ disguise = "k9"
+ disguise_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
+ disguise_pixel_offset = -16
+ disguise_dogborg = TRUE
+ if("Alina")
+ disguise = "alina-sec"
+ disguise_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
+ disguise_pixel_offset = -16
+ disguise_dogborg = TRUE
+ if("K9 Dark")
+ disguise = "k9dark"
+ disguise_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
+ disguise_pixel_offset = -16
+ disguise_dogborg = TRUE
+ if("Vale")
+ disguise = "valesec"
+ disguise_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
+ disguise_pixel_offset = -16
+ disguise_dogborg = TRUE
+ if("Drake")
+ disguise = "drakesec"
+ disguise_icon_override = 'sandcode/icons/mob/cyborg/drakemech.dmi'
+ disguise_pixel_offset = -16
+ disguise_dogborg = TRUE
+ else
+ return FALSE
+ if("Service")
+ var/static/list/service_icons = list(
+ "(Service) Waitress" = image(icon = 'icons/mob/robots.dmi', icon_state = "service_f"),
+ "(Service) Butler" = image(icon = 'icons/mob/robots.dmi', icon_state = "service_m"),
+ "(Service) Bro" = image(icon = 'icons/mob/robots.dmi', icon_state = "brobot"),
+ "(Service) Can" = image(icon = 'icons/mob/robots.dmi', icon_state = "kent"),
+ "(Service) Tophat" = image(icon = 'icons/mob/robots.dmi', icon_state = "tophat"),
+ "(Service) Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekserv"),
+ "(Service) Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyserv"),
+ "(Janitor) Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "janitor"),
+ "(Janitor) Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinajan"),
+ "(Janitor) Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekjan"),
+ "(Janitor) Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "canjan"),
+ "(Janitor) Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyres"),
+ "(Janitor) Drake" = image(icon = 'sandcode/icons/mob/cyborg/drakemech.dmi', icon_state = "drakejanitbox")
+ )
+ var/list/L = list("(Service) DarkK9" = "k50", "(Service) Vale" = "valeserv", "(Service) ValeDark" = "valeservdark",
+ "(Janitor) Scrubpuppy" = "scrubpup")
+ for(var/a in L)
+ var/image/wide = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = L[a])
+ wide.pixel_x = -16
+ service_icons[a] = wide
+ service_icons = sortList(service_icons)
+ var/borg_icon = show_radial_menu(R, R , service_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
+ if(!borg_icon)
+ return FALSE
+ switch(borg_icon)
+ if("(Service) Waitress")
+ disguise = "service_f"
+ disguise_icon_override = 'icons/mob/robots.dmi'
+ if("(Service) Butler")
+ disguise = "service_m"
+ disguise_icon_override = 'icons/mob/robots.dmi'
+ if("(Service) Bro")
+ disguise = "brobot"
+ disguise_icon_override = 'icons/mob/robots.dmi'
+ if("(Service) Can")
+ disguise = "kent"
+ disguise_icon_override = 'icons/mob/robots.dmi'
+ if("(Service) Tophat")
+ disguise = "tophat"
+ disguise_icon_override = 'icons/mob/robots.dmi'
+ if("(Service) Sleek")
+ disguise = "sleekserv"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("(Service) Heavy")
+ disguise = "heavyserv"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("(Service) DarkK9")
+ disguise = "k50"
+ disguise_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
+ disguise_pixel_offset = -16
+ disguise_dogborg = TRUE
+ if("(Service) Vale")
+ disguise = "valeserv"
+ disguise_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
+ disguise_pixel_offset = -16
+ disguise_dogborg = TRUE
+ if("(Service) ValeDark")
+ disguise = "valeservdark"
+ disguise_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
+ disguise_pixel_offset = -16
+ disguise_dogborg = TRUE
+ if("(Janitor) Default")
+ disguise = "janitor"
+ disguise_icon_override = 'icons/mob/robots.dmi'
+ if("(Janitor) Marina")
+ disguise = "marinajan"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("(Janitor) Sleek")
+ disguise = "sleekjan"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("(Janitor) Can")
+ disguise = "canjan"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("(Janitor) Heavy")
+ disguise = "heavyres"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("(Janitor) Scrubpuppy")
+ disguise = "scrubpup"
+ disguise_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
+ disguise_pixel_offset = -16
+ disguise_dogborg = TRUE
+ if("(Janitor) Drake")
+ disguise = "drakejanit"
+ disguise_icon_override = 'sandcode/icons/mob/cyborg/drakemech.dmi'
+ disguise_pixel_offset = -16
+ disguise_dogborg = TRUE
+ else
+ return FALSE
+ if("Miner")
+ var/static/list/mining_icons = list(
+ "Lavaland" = image(icon = 'icons/mob/robots.dmi', icon_state = "miner"),
+ "Asteroid" = image(icon = 'icons/mob/robots.dmi', icon_state = "minerOLD"),
+ "Droid" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "miner"),
+ "Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekmin"),
+ "Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinamin"),
+ "Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "canmin"),
+ "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavymin"),
+ "Drake" = image(icon = 'sandcode/icons/mob/cyborg/drakemech.dmi', icon_state = "drakeminebox")
+ )
+ var/list/L = list("Blade" = "blade", "Vale" = "valemine")
+ for(var/a in L)
+ var/image/wide = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = L[a])
+ wide.pixel_x = -16
+ mining_icons[a] = wide
+ mining_icons = sortList(mining_icons)
+ var/borg_icon = show_radial_menu(R, R , mining_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
+ if(!borg_icon)
+ return FALSE
+ switch(borg_icon)
+ if("Lavaland")
+ disguise = "miner"
+ disguise_icon_override = 'icons/mob/robots.dmi'
+ if("Asteroid")
+ disguise = "minerOLD"
+ disguise_icon_override = 'icons/mob/robots.dmi'
+ if("Droid")
+ disguise = "miner"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Sleek")
+ disguise = "sleekmin"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Can")
+ disguise = "canmin"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Marina")
+ disguise = "marinamin"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Spider")
+ disguise = "spidermin"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Heavy")
+ disguise = "heavymin"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Blade")
+ disguise = "blade"
+ disguise_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
+ disguise_pixel_offset = -16
+ disguise_dogborg = TRUE
+ if("Vale")
+ disguise = "valemine"
+ disguise_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
+ disguise_pixel_offset = -16
+ disguise_dogborg = TRUE
+ if("Drake")
+ disguise = "drakemine"
+ disguise_icon_override = 'sandcode/icons/mob/cyborg/drakemech.dmi'
+ disguise_pixel_offset = -16
+ disguise_dogborg = TRUE
+ else
+ return FALSE
+ if("Peacekeeper")
+ var/static/list/peace_icons = sortList(list(
+ "Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "peace"),
+ "Borgi" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "borgi"),
+ "Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "whitespider"),
+ "Drake" = image(icon = 'sandcode/icons/mob/cyborg/drakemech.dmi', icon_state = "drakepeacebox")
+ ))
+ var/borg_icon = show_radial_menu(R, R , peace_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
+ if(!borg_icon)
+ return FALSE
+ switch(borg_icon)
+ if("Default")
+ disguise = "peace"
+ disguise_icon_override = 'icons/mob/robots.dmi'
+ if("Spider")
+ disguise = "whitespider"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Borgi")
+ disguise = "borgi"
+ disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
+ if("Drake")
+ disguise = "drakepeace"
+ disguise_icon_override = 'sandcode/icons/mob/cyborg/drakemech.dmi'
+ disguise_pixel_offset = -16
+ disguise_dogborg = TRUE
+ else
+ return FALSE
+ if("Clown")
+ var/static/list/clown_icons = sortList(list(
+ "Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "clown")
+ ))
+ var/borg_icon = show_radial_menu(R, R , clown_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
+ if(!borg_icon)
+ return FALSE
+ switch(borg_icon)
+ if("Default")
+ disguise = "clown"
+ disguise_icon_override = 'icons/mob/robots.dmi'
+ else
+ return FALSE
+ if("Syndicate")
+ var/static/list/syndicatejack_icons = sortList(list(
+ "Saboteur" = image(icon = 'icons/mob/robots.dmi', icon_state = "synd_engi"),
+ "Medical" = image(icon = 'icons/mob/robots.dmi', icon_state = "synd_medical"),
+ "Assault" = image(icon = 'icons/mob/robots.dmi', icon_state = "synd_sec")
+ ))
+ var/borg_icon = show_radial_menu(R, R , syndicatejack_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
+ if(!borg_icon)
+ return FALSE
+ switch(borg_icon)
+ if("Saboteur")
+ disguise = "synd_engi"
+ disguise_icon_override = 'icons/mob/robots.dmi'
+ if("Medical")
+ disguise = "synd_medical"
+ disguise_icon_override = 'icons/mob/robots.dmi'
+ if("Assault")
+ disguise = "synd_sec"
+ disguise_icon_override = 'icons/mob/robots.dmi'
+ else
+ return FALSE
+ else
+ return FALSE
+
+ animation_playing = TRUE
+ to_chat(user, "You activate \the [src].")
+ playsound(src, 'sound/effects/seedling_chargeup.ogg', 100, TRUE, -6)
+ 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, TRUE, -6)
+ to_chat(user, "You are now disguised as the Nanotrasen cyborg \"[friendlyName]\".")
+ activate(user, module_selection)
+ 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
+ animation_playing = FALSE
+
+/obj/item/borg_shapeshifter/process()
+ if (user)
+ if (!user.cell || !user.cell.use(activationUpkeep))
+ disrupt(user)
+ else
+ return PROCESS_KILL
+
+/obj/item/borg_shapeshifter/proc/activate(mob/living/silicon/robot/user, disguiseModuleName)
+ START_PROCESSING(SSobj, src)
+ src.user = user
+ savedName = user.name
+ savedIcon = user.module.cyborg_base_icon
+ savedBubbleIcon = user.bubble_icon //tf is that
+ savedOverride = user.module.cyborg_icon_override
+ savedPixelOffset = user.module.cyborg_pixel_offset
+ savedModuleName = user.module.name
+ user.name = friendlyName
+ user.module.name = disguiseModuleName
+ user.module.cyborg_base_icon = disguise
+ user.module.cyborg_icon_override = disguise_icon_override
+ user.module.cyborg_pixel_offset = disguise_pixel_offset
+ user.module.dogborg = disguise_dogborg
+ user.bubble_icon = "robot"
+ active = TRUE
+ user.update_icons()
+
+ if(listeningTo == user)
+ return
+ if(listeningTo)
+ UnregisterSignal(listeningTo, signalCache)
+ RegisterSignal(user, signalCache, .proc/disrupt)
+ listeningTo = user
+
+/obj/item/borg_shapeshifter/proc/deactivate(mob/living/silicon/robot/user)
+ STOP_PROCESSING(SSobj, src)
+ if(listeningTo)
+ UnregisterSignal(listeningTo, signalCache)
+ listeningTo = null
+ do_sparks(5, FALSE, user)
+ user.name = savedName
+ user.module.name = savedModuleName
+ user.module.cyborg_base_icon = savedIcon
+ user.module.cyborg_icon_override = savedOverride
+ user.module.cyborg_pixel_offset = 0
+ user.module.dogborg = FALSE
+ user.bubble_icon = savedBubbleIcon
+ active = FALSE
+ user.update_icons()
+ disguise_pixel_offset = 0
+ disguise_dogborg = FALSE
+ src.user = user
+
+/obj/item/borg_shapeshifter/proc/disrupt(mob/living/silicon/robot/user)
+ if(active)
+ to_chat(user, "Your chameleon field deactivates.")
+ deactivate(user)
+
+/obj/item/borg_shapeshifter/stable
+ signalCache = list()
+ activationCost = 0
+ activationUpkeep = 0
+
+/obj/item/borg_shapeshifter/stable/activate(mob/living/silicon/robot/user, disguiseModuleName)
+ friendlyName = user.name
+ . = ..()
diff --git a/sandcode/code/game/objects/items/robot/robot_upgrades.dm b/sandcode/code/game/objects/items/robot/robot_upgrades.dm
index 1664200e60..888fd67747 100644
--- a/sandcode/code/game/objects/items/robot/robot_upgrades.dm
+++ b/sandcode/code/game/objects/items/robot/robot_upgrades.dm
@@ -1,3 +1,68 @@
+/obj/item/borg/upgrade/xwelding
+ name = "engineering cyborg experimental welding tool"
+ desc = "An experimental welding tool replacement for the engineering module's standard welding tool."
+ icon_state = "cyborg_upgrade3"
+ require_module = 1
+ module_type = list(/obj/item/robot_module/engineering)
+
+/obj/item/borg/upgrade/xwelding/action(mob/living/silicon/robot/R, user = usr)
+ . = ..()
+ if(.)
+ var/obj/item/weldingtool/largetank/cyborg/WT = locate() in R
+ var/obj/item/weldingtool/experimental/XW = locate() in R
+ if(!WT)
+ WT = locate() in R.module
+ if(!XW)
+ XW = locate() in R.module
+ if(XW)
+ to_chat(user, "This unit is already equipped with an experimental welding tool module.")
+ return FALSE
+ XW = new(R.module)
+ qdel(WT)
+ R.module.basic_modules += XW
+ R.module.add_module(XW, FALSE, TRUE)
+
+/obj/item/borg/upgrade/xwelding/deactivate(mob/living/silicon/robot/R, user = usr)
+ . = ..()
+ if (.)
+ for(var/obj/item/weldingtool/experimental/XW in R.module)
+ R.module.remove_module(XW, TRUE)
+
+ var/obj/item/weldingtool/largetank/cyborg/WT = new (R.module)
+ R.module.basic_modules += WT
+ R.module.add_module(WT, FALSE, TRUE)
+
+/* Shit doesnt work, work on it later
+/obj/item/borg/upgrade/plasma
+ name = "engineering cyborg plasma resource upgrade"
+ desc = "An upgrade that allows cyborgs the ability to use plasma and assorted plasma products."
+ icon_state = "cyborg_upgrade3"
+ require_module = 1
+ module_type = list(/obj/item/robot_module/engineering)
+*/
+
+/* Shit doesnt work, do it later
+/obj/item/borg/upgrade/plasma/action(mob/living/silicon/robot/R, user = usr)
+ . = ..()
+ if(.)
+ R.module.basic_modules += /obj/item/stack/sheet/plasmaglass/cyborg
+ R.module.add_module(/obj/item/stack/sheet/plasmaglass/cyborg, FALSE, TRUE)
+ R.module.basic_modules += /obj/item/stack/sheet/plasmarglass/cyborg
+ R.module.add_module(/obj/item/stack/sheet/plasmarglass/cyborg, FALSE, TRUE)
+ R.module.basic_modules += /obj/item/stack/sheet/plasteel/cyborg
+ R.module.add_module(/obj/item/stack/sheet/plasteel/cyborg, FALSE, TRUE)
+ R.module.basic_modules += /obj/item/stack/sheet/mineral/plasma/cyborg
+ R.module.add_module(/obj/item/stack/sheet/mineral/plasma/cyborg, FALSE, TRUE)
+
+/obj/item/borg/upgrade/plasma/deactivate(mob/living/silicon/robot/R, user = usr)
+ . = ..()
+ if (.)
+ R.module.remove_module(/obj/item/stack/sheet/plasmaglass/cyborg, TRUE)
+ R.module.remove_module(/obj/item/stack/sheet/plasmarglass/cyborg, TRUE)
+ R.module.remove_module(/obj/item/stack/sheet/plasteel/cyborg, TRUE)
+ R.module.remove_module(/obj/item/stack/sheet/mineral/plasma/cyborg, TRUE)
+*/
+
/obj/item/borg/upgrade/bsrpd
name = "engineering cyborg bluespace RPD"
desc = "A bluespace RPD replacement for the engineering module's standard RPD."
@@ -32,3 +97,122 @@
var/obj/item/pipe_dispenser/PD = new (R.module)
R.module.basic_modules += PD
R.module.add_module(PD, FALSE, TRUE)
+
+/obj/item/borg/upgrade/premiumka
+ name = "mining cyborg premium KA"
+ desc = "A premium kinetic accelerator replacement for the mining module's standard kinetic accelerator."
+ icon_state = "cyborg_upgrade3"
+ require_module = 1
+ module_type = list(/obj/item/robot_module/miner)
+
+/obj/item/borg/upgrade/premiumka/action(mob/living/silicon/robot/R, user = usr)
+ . = ..()
+ if(.)
+ for(var/obj/item/gun/energy/kinetic_accelerator/cyborg/KA in R.module)
+ for(var/obj/item/borg/upgrade/modkit/M in KA.modkits)
+ M.uninstall(src)
+ R.module.remove_module(KA, TRUE)
+
+ var/obj/item/gun/energy/kinetic_accelerator/premiumka/cyborg/PKA = new /obj/item/gun/energy/kinetic_accelerator/premiumka/cyborg(R.module)
+ R.module.basic_modules += PKA
+ R.module.add_module(PKA, FALSE, TRUE)
+
+/obj/item/borg/upgrade/premiumka/deactivate(mob/living/silicon/robot/R, user = usr)
+ . = ..()
+ if (.)
+ for(var/obj/item/gun/energy/kinetic_accelerator/premiumka/cyborg/PKA in R.module)
+ for(var/obj/item/borg/upgrade/modkit/M in PKA.modkits)
+ M.uninstall(src)
+ R.module.remove_module(PKA, TRUE)
+
+ var/obj/item/gun/energy/kinetic_accelerator/cyborg/KA = new (R.module)
+ R.module.basic_modules += KA
+ R.module.add_module(KA, FALSE, TRUE)
+
+/obj/item/borg/upgrade/expand/action(mob/living/silicon/robot/R, user = usr)
+ . = ..()
+ if(.)
+
+ if(R.hasExpanded)
+ to_chat(usr, "This unit already has an expand module installed!")
+ return FALSE
+
+ if(R.hasShrunk)
+ to_chat(usr, "This unit already has an shrink module installed!")
+ return FALSE
+
+ R.mob_transforming = TRUE
+ var/prev_locked_down = R.locked_down
+ R.SetLockdown(1)
+ R.anchored = TRUE
+ var/datum/effect_system/smoke_spread/smoke = new
+ smoke.set_up(1, R.loc)
+ smoke.start()
+ sleep(2)
+ for(var/i in 1 to 4)
+ playsound(R, pick('sound/items/drill_use.ogg', 'sound/items/jaws_cut.ogg', 'sound/items/jaws_pry.ogg', 'sound/items/welder.ogg', 'sound/items/ratchet.ogg'), 80, 1, -1)
+ sleep(12)
+ if(!prev_locked_down)
+ R.SetLockdown(0)
+ R.anchored = FALSE
+ R.mob_transforming = FALSE
+ R.transform = R.transform.Scale(1.25, 1.25)
+ R.hasExpanded = TRUE
+
+/obj/item/borg/upgrade/expand/deactivate(mob/living/silicon/robot/R, user = usr)
+ . = ..()
+ if (.)
+ R.transform = R.transform.Scale(0.8, 0.8)
+ R.hasExpanded = FALSE
+
+/obj/item/borg/upgrade/shrink
+ name = "borg shrinker"
+ desc = "A cyborg resizer, it makes a cyborg small."
+ icon_state = "cyborg_upgrade3"
+
+/obj/item/borg/upgrade/shrink/action(mob/living/silicon/robot/R, user = usr)
+ . = ..()
+ if(.)
+
+ if(R.hasShrunk)
+ to_chat(usr, "This unit already has an shrink module installed!")
+ return FALSE
+
+ if(R.hasExpanded)
+ to_chat(usr, "This unit already has an expand module installed!")
+ return FALSE
+
+
+ R.mob_transforming = TRUE
+ var/prev_locked_down = R.locked_down
+ R.SetLockdown(1)
+ R.anchored = TRUE
+ var/datum/effect_system/smoke_spread/smoke = new
+ smoke.set_up(1, R.loc)
+ smoke.start()
+ sleep(2)
+ for(var/i in 1 to 4)
+ playsound(R, pick('sound/items/drill_use.ogg', 'sound/items/jaws_cut.ogg', 'sound/items/jaws_pry.ogg', 'sound/items/welder.ogg', 'sound/items/ratchet.ogg'), 80, 1, -1)
+ sleep(12)
+ if(!prev_locked_down)
+ R.SetLockdown(0)
+ R.anchored = FALSE
+ R.mob_transforming = FALSE
+ R.transform = R.transform.Scale(0.75, 0.75)
+ R.hasShrunk = TRUE
+
+/obj/item/borg/upgrade/shrink/deactivate(mob/living/silicon/robot/R, user = usr)
+ . = ..()
+ if (.)
+ R.transform = R.transform.Scale((4/3), (4/3))
+ R.hasShrunk = FALSE
+
+/obj/item/borg/upgrade/transform/syndicatejack
+ name = "borg module picker (Syndicate)"
+ desc = "Allows you to to turn a cyborg into a experimental syndicate cyborg."
+ icon_state = "cyborg_upgrade3"
+ new_module = /obj/item/robot_module/syndicatejack
+
+/obj/item/borg/upgrade/transform/syndicatejack/action(mob/living/silicon/robot/R, user = usr)
+ if(R.emagged)
+ return ..()
diff --git a/sandcode/code/game/objects/items/stacks/sheets/glass.dm b/sandcode/code/game/objects/items/stacks/sheets/glass.dm
new file mode 100644
index 0000000000..b8080cc825
--- /dev/null
+++ b/sandcode/code/game/objects/items/stacks/sheets/glass.dm
@@ -0,0 +1,40 @@
+/obj/item/stack/sheet/plasmaglass/cyborg
+ custom_materials = null
+ //var/datum/robot_energy_storage/glasource
+ //var/datum/robot_energy_storage/plasource
+ //var/glacost = 250
+ //var/placost = 250
+ cost = 500
+ is_cyborg = 1
+/* commented out to pick shit up
+/obj/item/stack/sheet/plasmaglass/cyborg/get_amount()
+ return min(round(plasource.energy / placost), round(glasource.energy / glacost))
+
+/obj/item/stack/sheet/plasmaglass/cyborg/use(used, transfer = FALSE) // Requires special checks, because it uses two storages
+ plasource.use_charge(used * placost)
+ glasource.use_charge(used * glacost)
+
+/obj/item/stack/sheet/plasmaglass/cyborg/add(amount)
+ plasource.add_charge(amount * placost)
+ glasource.add_charge(amount * glacost)
+*/
+/obj/item/stack/sheet/plasmarglass/cyborg
+ custom_materials = null
+ //var/datum/robot_energy_storage/glasource
+ //var/datum/robot_energy_storage/plasource
+ //var/glacost = 500
+ //var/placost = 500
+ cost = 1000
+ is_cyborg = 1
+/* commented out to pick shit up
+/obj/item/stack/sheet/plasmarglass/cyborg/get_amount()
+ return min(round(glasource.energy / glacost), round(plasource.energy / placost))
+
+/obj/item/stack/sheet/plasmarglass/cyborg/use(used, transfer = FALSE) // Requires special checks, because it uses two storages
+ glasource.use_charge(used * glacost)
+ plasource.use_charge(used * placost)
+
+/obj/item/stack/sheet/plasmarglass/cyborg/add(amount)
+ glasource.add_charge(amount * glacost)
+ plasource.add_charge(amount * placost)
+*/
diff --git a/sandcode/code/game/objects/items/stacks/sheets/mineral.dm b/sandcode/code/game/objects/items/stacks/sheets/mineral.dm
new file mode 100644
index 0000000000..0ac8a622fd
--- /dev/null
+++ b/sandcode/code/game/objects/items/stacks/sheets/mineral.dm
@@ -0,0 +1,15 @@
+/obj/item/stack/sheet/mineral/plasma/cyborg
+ custom_materials = null
+ is_cyborg = 1
+ cost = 500
+
+/obj/item/stack/sheet/mineral/plasma/cyborg/attackby(obj/item/W as obj, mob/user as mob, params)
+ if(W.get_temperature() > 9999)//If the temperature of the object is over 9999, then ignite
+ var/turf/T = get_turf(src)
+ message_admins("Plasma sheets attempted to be ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_VERBOSEJMP(T)]")
+ log_game("Plasma sheets attempted to be ignited by [key_name(user)] in [AREACOORD(T)]")
+ else
+ return ..()
+
+/obj/item/stack/sheet/mineral/plasma/cyborg/fire_act(exposed_temperature, exposed_volume)
+ atmos_spawn_air("plasma=[amount*0];TEMP=[null]")
diff --git a/sandcode/code/game/objects/items/stacks/sheets/sheet_types.dm b/sandcode/code/game/objects/items/stacks/sheets/sheet_types.dm
new file mode 100644
index 0000000000..9fd74538bb
--- /dev/null
+++ b/sandcode/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -0,0 +1,34 @@
+/obj/item/stack/sheet/plasteel/cyborg
+ custom_materials = null
+ //var/datum/robot_energy_storage/metsource
+ //var/datum/robot_energy_storage/plasource
+ //var/metcost = 250
+ //var/placost = 250
+ cost = 500
+ is_cyborg = 1
+/* Commented out to pick up shit
+/obj/item/stack/sheet/plasteel/cyborg/get_amount()
+ return min(round(source.energy / metcost), round(plasource.energy / placost))
+
+/obj/item/stack/sheet/plasteel/cyborg/use(used, transfer = FALSE) // Requires special checks, because it uses two storages
+ source.use_charge(used * metcost)
+ plasource.use_charge(used * placost)
+
+/obj/item/stack/sheet/plasteel/cyborg/add(amount)
+ source.add_charge(amount * metcost)
+ plasource.add_charge(amount * placost)
+*/
+
+/obj/item/stack/sheet/mineral/wood
+ name = "wooden plank"
+ desc = "One can only guess that this is a bunch of wood. You might be able to make a stake with this if you use something sharp on it"
+ singular_name = "wood plank"
+ icon_state = "sheet-wood"
+ item_state = "sheet-wood"
+ icon = 'icons/obj/stack_objects.dmi'
+ sheettype = "wood"
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 0)
+ resistance_flags = FLAMMABLE
+ merge_type = /obj/item/stack/sheet/mineral/wood
+ novariants = TRUE
+ grind_results = list(/datum/reagent/cellulose = 20)
diff --git a/sandcode/code/game/objects/structures/ghost_role_spawners.dm b/sandcode/code/game/objects/structures/ghost_role_spawners.dm
new file mode 100644
index 0000000000..d7a9bb64b5
--- /dev/null
+++ b/sandcode/code/game/objects/structures/ghost_role_spawners.dm
@@ -0,0 +1,41 @@
+/obj/effect/mob_spawn/robot
+ mob_type = /mob/living/silicon/robot
+ assignedrole = "Ghost Role"
+
+/obj/effect/mob_spawn/robot/Initialize()
+ . = ..()
+
+/obj/effect/mob_spawn/robot/equip(mob/living/silicon/robot/R)
+ . = ..()
+
+/obj/effect/mob_spawn/robot/ghostcafe
+ name = "Cafe Robotic Storage"
+ uses = -1
+ icon = 'sandcode/icons/obj/machines/robot_storage.dmi'
+ icon_state = "robostorage"
+ mob_name = "a cafe robot"
+ roundstart = FALSE
+ anchored = TRUE
+ density = FALSE
+ death = FALSE
+ assignedrole = "Cafe Robot"
+ short_desc = "You are a Cafe Robot!"
+ flavour_text = "Who could have thought? This awesome local cafe accepts cyborgs too!"
+ skip_reentry_check = TRUE
+ banType = ROLE_GHOSTCAFE
+ mob_type = /mob/living/silicon/robot/modules/roleplay
+
+/obj/effect/mob_spawn/robot/ghostcafe/special(mob/living/silicon/robot/new_spawn)
+ if(new_spawn.client)
+ new_spawn.updatename(new_spawn.client)
+ new_spawn.gender = NEUTER
+ var/area/A = get_area(src)
+ new_spawn.AddElement(/datum/element/ghost_role_eligibility, free_ghosting = TRUE)
+ new_spawn.AddElement(/datum/element/dusts_on_catatonia)
+ new_spawn.AddElement(/datum/element/dusts_on_leaving_area, list(A.type, /area/hilbertshotel))
+ ADD_TRAIT(new_spawn, TRAIT_SIXTHSENSE, GHOSTROLE_TRAIT)
+ ADD_TRAIT(new_spawn, TRAIT_EXEMPT_HEALTH_EVENTS, GHOSTROLE_TRAIT)
+ ADD_TRAIT(new_spawn, TRAIT_NO_MIDROUND_ANTAG, GHOSTROLE_TRAIT) //The mob can't be made into a random antag, they are still eligible for ghost roles popups.
+ to_chat(new_spawn,"Ghosting is free!")
+ var/datum/action/toggle_dead_chat_mob/D = new(new_spawn)
+ D.Grant(new_spawn)
diff --git a/sandcode/code/modules/mob/living/silicon/robot/robot.dm b/sandcode/code/modules/mob/living/silicon/robot/robot.dm
new file mode 100644
index 0000000000..a9f6393353
--- /dev/null
+++ b/sandcode/code/modules/mob/living/silicon/robot/robot.dm
@@ -0,0 +1,21 @@
+/mob/living/silicon/robot
+ speed = 0.2
+ var/hasShrunk = FALSE
+
+/mob/living/silicon/robot/modules/roleplay
+ lawupdate = FALSE
+ scrambledcodes = TRUE // Roleplay borgs aren't real
+ set_module = /obj/item/robot_module/roleplay
+
+/mob/living/silicon/robot/modules/roleplay/Initialize()
+ . = ..()
+ cell = new /obj/item/stock_parts/cell/infinite(src, 30000)
+ laws = new /datum/ai_laws/roleplay()
+ //You aren't allowed to unlock, not sorry
+ src.verbs -= /mob/living/silicon/robot/verb/unlock_own_cover
+ //This part is because the camera stays in the list, so we'll just do a check
+ if(!QDELETED(builtInCamera))
+ QDEL_NULL(builtInCamera)
+
+/mob/living/silicon/robot/modules/roleplay/binarycheck()
+ return 0 //Roleplay borgs aren't truly borgs
diff --git a/sandcode/code/modules/mob/living/silicon/robot/robot_modules.dm b/sandcode/code/modules/mob/living/silicon/robot/robot_modules.dm
new file mode 100644
index 0000000000..8c24bb06e2
--- /dev/null
+++ b/sandcode/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -0,0 +1,216 @@
+/obj/item/robot_module/proc/add_module(obj/item/I, nonstandard, requires_rebuild)
+ rad_flags |= RAD_NO_CONTAMINATE
+ if(istype(I, /obj/item/stack))
+ var/obj/item/stack/S = I
+
+ if(is_type_in_list(S, list(/obj/item/stack/sheet/metal, /obj/item/stack/rods, /obj/item/stack/tile/plasteel)))
+ if(S.custom_materials?.len && S.custom_materials[SSmaterials.GetMaterialRef(/datum/material/iron)])
+ S.cost = S.custom_materials[SSmaterials.GetMaterialRef(/datum/material/iron)] * 0.25
+ S.source = get_or_create_estorage(/datum/robot_energy_storage/metal)
+
+ else if(istype(S, /obj/item/stack/sheet/glass))
+ S.cost = 500
+ S.source = get_or_create_estorage(/datum/robot_energy_storage/glass)
+
+ else if(istype(S, /obj/item/stack/sheet/rglass/cyborg))
+ var/obj/item/stack/sheet/rglass/cyborg/G = S
+ G.source = get_or_create_estorage(/datum/robot_energy_storage/metal)
+ G.glasource = get_or_create_estorage(/datum/robot_energy_storage/glass)
+
+ else if(istype(S, /obj/item/stack/sheet/plasmaglass/cyborg))
+ //var/obj/item/stack/sheet/plasmaglass/cyborg/G = S
+ //G.plasource = get_or_create_estorage(/datum/robot_energy_storage/plasma)
+ //G.glasource = get_or_create_estorage(/datum/robot_energy_storage/glass)
+ S.cost = 500
+ S.source = get_or_create_estorage(/datum/robot_energy_storage/plasma)
+
+ else if(istype(S, /obj/item/stack/sheet/plasmarglass/cyborg))
+ //var/obj/item/stack/sheet/plasmarglass/cyborg/G = S
+ //G.plasource = get_or_create_estorage(/datum/robot_energy_storage/plasma)
+ //G.glasource = get_or_create_estorage(/datum/robot_energy_storage/glass)
+ S.cost = 1000
+ S.source = get_or_create_estorage(/datum/robot_energy_storage/plasma)
+
+ else if(istype(S, /obj/item/stack/sheet/plasteel/cyborg))
+ //var/obj/item/stack/sheet/plasteel/cyborg/G = S
+ //G.source = get_or_create_estorage(/datum/robot_energy_storage/metal)
+ //G.plasource = get_or_create_estorage(/datum/robot_energy_storage/plasma)
+ S.cost = 500
+ S.source = get_or_create_estorage(/datum/robot_energy_storage/plasma)
+
+ else if(istype(S, /obj/item/stack/sheet/mineral/plasma/cyborg))
+ S.cost = 500
+ S.source = get_or_create_estorage(/datum/robot_energy_storage/plasma)
+
+ else if(istype(S, /obj/item/stack/medical))
+ S.cost = 250
+ S.source = get_or_create_estorage(/datum/robot_energy_storage/medical)
+
+ else if(istype(S, /obj/item/stack/cable_coil))
+ S.cost = 1
+ S.source = get_or_create_estorage(/datum/robot_energy_storage/wire)
+
+ else if(istype(S, /obj/item/stack/marker_beacon))
+ S.cost = 1
+ S.source = get_or_create_estorage(/datum/robot_energy_storage/beacon)
+
+ else if(istype(S, /obj/item/stack/packageWrap))
+ S.cost = 1
+ S.source = get_or_create_estorage(/datum/robot_energy_storage/wrapping_paper)
+
+ if(S && S.source)
+ S.custom_materials = null
+ S.is_cyborg = 1
+
+ if(I.loc != src)
+ I.forceMove(src)
+ modules += I
+ ADD_TRAIT(I, TRAIT_NODROP, CYBORG_ITEM_TRAIT)
+ I.mouse_opacity = MOUSE_OPACITY_OPAQUE
+ if(nonstandard)
+ added_modules += I
+ if(requires_rebuild)
+ rebuild_modules()
+ return I
+
+/obj/item/robot_module/engineering/Initialize()
+ basic_modules += /obj/item/pen
+ basic_modules += /obj/item/electronics/airlock
+ basic_modules += /obj/item/stack/sheet/plasmaglass/cyborg
+ basic_modules += /obj/item/stack/sheet/plasmarglass/cyborg
+ basic_modules += /obj/item/stack/sheet/plasteel/cyborg
+ basic_modules += /obj/item/stack/sheet/mineral/plasma/cyborg
+ . = ..()
+
+/obj/item/robot_module/butler/Initialize()
+ basic_modules -= /obj/item/reagent_containers/borghypo/borgshaker
+ basic_modules += /obj/item/reagent_containers/borghypo/borgshaker/beershaker
+ basic_modules += /obj/item/reagent_containers/borghypo/borgshaker/juiceshaker
+ basic_modules += /obj/item/reagent_containers/borghypo/borgshaker/sodashaker
+ basic_modules += /obj/item/reagent_containers/borghypo/borgshaker/miscshaker
+ . = ..()
+
+/obj/item/robot_module/miner/Initialize()
+ basic_modules += /obj/item/card/id/miningborg
+ . = ..()
+
+/datum/robot_energy_storage/plasma
+ name = "Plasma Buffer Container"
+ recharge_rate = 0
+
+/obj/item/robot_module/syndicatejack
+ name = "Syndicate"
+ basic_modules = list(
+ /obj/item/assembly/flash/cyborg,
+ /obj/item/borg/sight/thermal,
+ /obj/item/extinguisher,
+ /obj/item/weldingtool/experimental,
+ /obj/item/screwdriver/nuke,
+ /obj/item/wrench/cyborg,
+ /obj/item/crowbar/cyborg,
+ /obj/item/wirecutters/cyborg,
+ /obj/item/multitool/cyborg,
+ /obj/item/weapon/gripper,
+ /obj/item/cyborg_clamp,
+ /obj/item/lightreplacer/cyborg,
+ /obj/item/stack/sheet/metal/cyborg,
+ /obj/item/stack/sheet/glass/cyborg,
+ /obj/item/stack/sheet/rglass/cyborg,
+ /obj/item/stack/rods/cyborg,
+ /obj/item/stack/tile/plasteel/cyborg,
+ /obj/item/destTagger/borg,
+ /obj/item/stack/cable_coil/cyborg,
+ /obj/item/restraints/handcuffs/cable/zipties,
+ /obj/item/stack/medical/gauze/cyborg,
+ /obj/item/shockpaddles/cyborg,
+ /obj/item/healthanalyzer/advanced,
+ /obj/item/surgical_drapes/advanced,
+ /obj/item/retractor/advanced,
+ /obj/item/surgicaldrill/advanced,
+ /obj/item/scalpel/advanced,
+ /obj/item/gun/medbeam,
+ /obj/item/reagent_containers/borghypo/syndicate,
+ /obj/item/borg/lollipop,
+ /obj/item/holosign_creator/cyborg,
+ /obj/item/stamp/chameleon,
+ /obj/item/borg_shapeshifter
+ )
+
+ ratvar_modules = list(
+ /obj/item/clockwork/slab/cyborg/medical,
+ /obj/item/clockwork/slab/cyborg/engineer,
+ /obj/item/clockwork/replica_fabricator/cyborg)
+
+ cyborg_base_icon = "synd_engi"
+ moduleselect_icon = "malf"
+ magpulsing = TRUE
+ hat_offset = INFINITY
+ canDispose = TRUE
+
+/obj/item/robot_module/syndicatejack/be_transformed_to(obj/item/robot_module/old_module)
+ var/mob/living/silicon/robot/R = loc
+ var/static/list/syndicatejack_icons = sortList(list(
+ "Saboteur" = image(icon = 'icons/mob/robots.dmi', icon_state = "synd_engi"),
+ "Medical" = image(icon = 'icons/mob/robots.dmi', icon_state = "synd_medical"),
+ "Assault" = image(icon = 'icons/mob/robots.dmi', icon_state = "synd_sec"),
+ ))
+ var/syndiejack_icon = show_radial_menu(R, R , syndicatejack_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
+ switch(syndiejack_icon)
+ if("Saboteur")
+ cyborg_base_icon = "synd_engi"
+ cyborg_icon_override = 'icons/mob/robots.dmi'
+ if("Medical")
+ cyborg_base_icon = "synd_medical"
+ cyborg_icon_override = 'icons/mob/robots.dmi'
+ if("Assault")
+ cyborg_base_icon = "synd_sec"
+ cyborg_icon_override = 'icons/mob/robots.dmi'
+ else
+ return FALSE
+ return ..()
+
+/obj/item/robot_module/syndicatejack/rebuild_modules()
+ ..()
+ var/mob/living/silicon/robot/syndicatejack = loc
+ syndicatejack.scrambledcodes = TRUE // We're rouge now
+
+/obj/item/robot_module/syndicatejack/remove_module(obj/item/I, delete_after)
+ ..()
+ var/mob/living/silicon/robot/syndicatejack = loc
+ syndicatejack.scrambledcodes = FALSE // Friends with the AI again
+
+/obj/item/robot_module/roleplay
+ name = "Roleplay"
+ basic_modules = list(
+ /obj/item/assembly/flash/cyborg,
+ /obj/item/extinguisher/mini,
+ /obj/item/weldingtool/largetank/cyborg,
+ /obj/item/screwdriver/cyborg,
+ /obj/item/wrench/cyborg,
+ /obj/item/crowbar/cyborg,
+ /obj/item/wirecutters/cyborg,
+ /obj/item/multitool/cyborg,
+ /obj/item/stack/sheet/metal/cyborg,
+ /obj/item/stack/sheet/glass/cyborg,
+ /obj/item/stack/sheet/rglass/cyborg,
+ /obj/item/stack/rods/cyborg,
+ /obj/item/stack/tile/plasteel/cyborg,
+ /obj/item/stack/cable_coil/cyborg,
+ /obj/item/restraints/handcuffs/cable/zipties,
+ /obj/item/rsf/cyborg,
+ /obj/item/reagent_containers/food/drinks/drinkingglass,
+ /obj/item/reagent_containers/borghypo/borgshaker/beershaker,
+ /obj/item/reagent_containers/borghypo/borgshaker/juiceshaker,
+ /obj/item/reagent_containers/borghypo/borgshaker/sodashaker,
+ /obj/item/reagent_containers/borghypo/borgshaker/miscshaker,
+ /obj/item/soap/nanotrasen,
+ /obj/item/borg/cyborghug,
+ /obj/item/dogborg_nose,
+ /obj/item/dogborg_tongue,
+ /obj/item/borg_shapeshifter/stable)
+ moduleselect_icon = "standard"
+ hat_offset = -3
+
+/obj/item/robot_module/Initialize()
+ basic_modules += /obj/item/dildo/custom
+ . = ..()
diff --git a/sandcode/code/modules/reagents/reagent_containers/borghydro.dm b/sandcode/code/modules/reagents/reagent_containers/borghydro.dm
new file mode 100644
index 0000000000..7880062c70
--- /dev/null
+++ b/sandcode/code/modules/reagents/reagent_containers/borghydro.dm
@@ -0,0 +1,128 @@
+/*
+Borg Shaker
+*/
+/obj/item/reagent_containers/borghypo/borgshaker/beershaker
+ name = "cyborg shaker"
+ desc = "An advanced drink synthesizer and mixer."
+ icon = 'sandcode/icons/obj/drinks.dmi'
+ icon_state = "beershaker"
+ possible_transfer_amounts = list(5,10,20)
+ charge_cost = 20 //Lots of reagents all regenerating at once, so the charge cost is lower. They also regenerate faster.
+ recharge_time = 1
+ accepts_reagent_upgrades = FALSE
+ reagent_ids = list( /datum/reagent/consumable/ethanol/beer,
+ /datum/reagent/consumable/ethanol/whiskey,
+ /datum/reagent/consumable/ethanol/vodka,
+ /datum/reagent/consumable/ethanol/rum,
+ /datum/reagent/consumable/ethanol/gin,
+ /datum/reagent/consumable/ethanol/tequila,
+ /datum/reagent/consumable/ethanol/vermouth,
+ /datum/reagent/consumable/ethanol/wine,
+ /datum/reagent/consumable/ethanol/kahlua,
+ /datum/reagent/consumable/ethanol/cognac,
+ /datum/reagent/consumable/ethanol/ale,
+ /datum/reagent/consumable/ethanol/fernet,
+ /datum/reagent/consumable/ethanol/triple_sec,
+ /datum/reagent/consumable/nothing,
+ /datum/reagent/consumable/laughter,
+ /datum/reagent/consumable/ethanol/creme_de_menthe,
+ /datum/reagent/consumable/ethanol/creme_de_cacao,
+ /datum/reagent/consumable/ethanol/creme_de_coconut,
+ /datum/reagent/consumable/ethanol/champagne,
+ /datum/reagent/consumable/ethanol/thirteenloko,
+ /datum/reagent/consumable/ethanol/absinthe,
+ /datum/reagent/consumable/ethanol/hooch,
+ /datum/reagent/consumable/ethanol/moonshine)
+
+
+/obj/item/reagent_containers/borghypo/borgshaker/juiceshaker
+ name = "cyborg shaker"
+ desc = "An advanced drink synthesizer and mixer."
+ icon = 'sandcode/icons/obj/drinks.dmi'
+ icon_state = "juiceshaker"
+ possible_transfer_amounts = list(5,10,20)
+ charge_cost = 20 //Lots of reagents all regenerating at once, so the charge cost is lower. They also regenerate faster.
+ recharge_time = 1
+ accepts_reagent_upgrades = FALSE
+ reagent_ids = list( /datum/reagent/consumable/orangejuice,
+ /datum/reagent/consumable/limejuice,
+ /datum/reagent/consumable/tomatojuice,
+ /datum/reagent/consumable/carrotjuice,
+ /datum/reagent/consumable/berryjuice,
+ /datum/reagent/consumable/applejuice,
+ /datum/reagent/consumable/peachjuice,
+ /datum/reagent/consumable/strawberryjuice,
+ /datum/reagent/consumable/pineapplejuice,
+ /datum/reagent/consumable/watermelonjuice,
+ /datum/reagent/consumable/parsnipjuice,
+ /datum/reagent/consumable/grapejuice,
+ /datum/reagent/consumable/potato_juice,
+ /datum/reagent/consumable/pumpkinjuice,
+ /datum/reagent/consumable/lemonjuice)
+
+/obj/item/reagent_containers/borghypo/borgshaker/sodashaker
+ name = "cyborg shaker"
+ desc = "An advanced drink synthesizer and mixer."
+ icon = 'sandcode/icons/obj/drinks.dmi'
+ icon_state = "sodashaker"
+ possible_transfer_amounts = list(5,10,20)
+ charge_cost = 20 //Lots of reagents all regenerating at once, so the charge cost is lower. They also regenerate faster.
+ recharge_time = 1
+ accepts_reagent_upgrades = FALSE
+ reagent_ids = list( /datum/reagent/consumable/space_cola,
+ /datum/reagent/consumable/nuka_cola,
+ /datum/reagent/consumable/spacemountainwind,
+ /datum/reagent/consumable/dr_gibb,
+ /datum/reagent/consumable/space_up,
+ /datum/reagent/consumable/lemon_lime,
+ /datum/reagent/consumable/pwr_game,
+ /datum/reagent/consumable/shamblers,
+ /datum/reagent/consumable/buzz_fuzz,
+ /datum/reagent/consumable/grey_bull,
+ /datum/reagent/consumable/cream_soda,
+ /datum/reagent/consumable/sol_dry,
+ /datum/reagent/consumable/tonic,
+ /datum/reagent/consumable/sodawater)
+
+/obj/item/reagent_containers/borghypo/borgshaker/miscshaker
+ name = "cyborg shaker"
+ desc = "An advanced drink synthesizer and mixer."
+ icon = 'sandcode/icons/obj/drinks.dmi'
+ icon_state = "miscshaker"
+ possible_transfer_amounts = list(5,10,20)
+ charge_cost = 20 //Lots of reagents all regenerating at once, so the charge cost is lower. They also regenerate faster.
+ recharge_time = 1
+ accepts_reagent_upgrades = FALSE
+ reagent_ids = list( /datum/reagent/consumable/grenadine,
+ /datum/reagent/consumable/banana,
+ /datum/reagent/consumable/honey,
+ /datum/reagent/consumable/sugar,
+ /datum/reagent/consumable/vanilla,
+ /datum/reagent/blood/synthetics,
+ /datum/reagent/consumable/capsaicin,
+ /datum/reagent/consumable/coco,
+ /datum/reagent/consumable/menthol,
+ /datum/reagent/consumable/ice,
+ /datum/reagent/consumable/cream,
+ /datum/reagent/consumable/milk,
+ /datum/reagent/consumable/soymilk,
+ /datum/reagent/consumable/coconutmilk,
+ /datum/reagent/consumable/coffee,
+ /datum/reagent/consumable/tea,
+ /datum/reagent/consumable/lemonade,
+ /datum/reagent/water)
+
+/obj/item/reagent_containers/borghypo/borgshaker/hacked
+ name = "cyborg shaker"
+ desc = "Will mix drinks that knock them dead."
+ icon = 'icons/obj/drinks.dmi'
+ icon_state = "threemileislandglass"
+ possible_transfer_amounts = list(5,10,20)
+ charge_cost = 20 //Lots of reagents all regenerating at once, so the charge cost is lower. They also regenerate faster.
+ recharge_time = 1
+ accepts_reagent_upgrades = FALSE
+ reagent_ids = list( /datum/reagent/toxin/fakebeer,
+ /datum/reagent/consumable/poisonberryjuice,
+ /datum/reagent/toxin/itching_powder,
+ /datum/reagent/toxin/bungotoxin,
+ /datum/reagent/consumable/superlaughter)
diff --git a/sandcode/code/modules/research/designs/mechfabricator_designs.dm b/sandcode/code/modules/research/designs/mechfabricator_designs.dm
index 64cebc1e39..43bf0f3f09 100644
--- a/sandcode/code/modules/research/designs/mechfabricator_designs.dm
+++ b/sandcode/code/modules/research/designs/mechfabricator_designs.dm
@@ -1,3 +1,21 @@
+/datum/design/borg_upgrade_xwelding
+ name = "Cyborg Upgrade (Experimental Welding Tool)"
+ id = "borg_upgrade_xwelding"
+ build_type = MECHFAB
+ build_path = /obj/item/borg/upgrade/xwelding
+ materials = list(/datum/material/iron = 1000, /datum/material/plasma = 1000, /datum/material/titanium = 1000)
+ construction_time = 100
+ category = list("Cyborg Upgrade Modules")
+/* Shit doesnt work, work on it later
+/datum/design/borg_upgrade_plasma
+ name = "Cyborg Upgrade (Plasma Resource)"
+ id = "borg_upgrade_plasma"
+ build_type = MECHFAB
+ build_path = /obj/item/borg/upgrade/plasma
+ materials = list(/datum/material/plasma = 1000, /datum/material/bluespace = 1000)
+ construction_time = 100
+ category = list("Cyborg Upgrade Modules")
+*/
/datum/design/borg_upgrade_bsrpd
name = "Cyborg Upgrade (Bluespace RPD)"
id = "borg_upgrade_bsrpd"
@@ -7,6 +25,34 @@
construction_time = 100
category = list("Cyborg Upgrade Modules")
+/datum/design/borg_upgrade_premiumka
+ name = "Cyborg Upgrade (Premium Kinetic Accelerator)"
+ id = "borg_upgrade_premiumka"
+ build_type = MECHFAB
+ build_path = /obj/item/borg/upgrade/premiumka
+ materials = list(/datum/material/iron=8000, /datum/material/glass=4000, /datum/material/titanium=2000)
+ construction_time = 120
+ category = list("Cyborg Upgrade Modules")
+
+/datum/design/borg_upgrade_expand
+ name = "Cyborg Upgrade (Expand)"
+ id = "borg_upgrade_expand"
+ build_type = MECHFAB
+ build_path = /obj/item/borg/upgrade/expand
+ materials = list(/datum/material/iron=20000, /datum/material/glass=5000)
+ construction_time = 120
+ category = list("Cyborg Upgrade Modules")
+
+/datum/design/borg_upgrade_shrink
+ name = "Cyborg Upgrade (shrink)"
+ id = "borg_upgrade_shrink"
+ build_type = MECHFAB
+ build_path = /obj/item/borg/upgrade/shrink
+ materials = list(/datum/material/iron=20000, /datum/material/glass=5000)
+ construction_time = 120
+ category = list("Cyborg Upgrade Modules")
+
+
///Power Armor
/datum/design/powerarmor_skeleton
name = "Power Armor Skeleton"
diff --git a/sandcode/code/modules/research/techweb/nodes/robotics_nodes.dm b/sandcode/code/modules/research/techweb/nodes/robotics_nodes.dm
index db873a544b..4fc02785a7 100644
--- a/sandcode/code/modules/research/techweb/nodes/robotics_nodes.dm
+++ b/sandcode/code/modules/research/techweb/nodes/robotics_nodes.dm
@@ -5,3 +5,13 @@
prereq_ids = list("adv_biotech", "adv_bluespace", "adv_robotics")
design_ids = list("powerarmor_skeleton","powerarmor_torso","powerarmor_helmet","powerarmor_armR","powerarmor_armL","powerarmor_legR","powerarmor_legL")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500)
+
+/datum/techweb_node/adv_robotics/New()
+ design_ids += "borg_upgrade_premiumka"
+ . = ..()
+
+/datum/techweb_node/cyborg_upg_util/New()
+ design_ids += "borg_upgrade_xwelding"
+ design_ids += "borg_upgrade_shrink"
+ //design_ids += "borg_upgrade_plasma"
+ . = ..()
diff --git a/sandcode/code/modules/ruins/spaceruin_code/hilbertshotel.dm b/sandcode/code/modules/ruins/spaceruin_code/hilbertshotel.dm
new file mode 100644
index 0000000000..0f90b4b90b
--- /dev/null
+++ b/sandcode/code/modules/ruins/spaceruin_code/hilbertshotel.dm
@@ -0,0 +1,3 @@
+/obj/item/hilbertshotel/ghostdojo/attack_robot(mob/user)
+ . = ..()
+ interact(user)
diff --git a/sandcode/icons/obj/drinks.dmi b/sandcode/icons/obj/drinks.dmi
new file mode 100644
index 0000000000..898ee57b66
Binary files /dev/null and b/sandcode/icons/obj/drinks.dmi differ
diff --git a/sandcode/icons/obj/machines/robot_storage.dmi b/sandcode/icons/obj/machines/robot_storage.dmi
new file mode 100644
index 0000000000..317c540fde
Binary files /dev/null and b/sandcode/icons/obj/machines/robot_storage.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index f21d62875e..7c3673bee2 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -3615,6 +3615,7 @@
#include "sandcode\code\__DEFINES\wires.dm"
#include "sandcode\code\_onclick\hud\screen_objects.dm"
#include "sandcode\code\datums\action.dm"
+#include "sandcode\code\datums\ai_laws.dm"
#include "sandcode\code\datums\shuttles.dm"
#include "sandcode\code\datums\interactions\_interaction.dm"
#include "sandcode\code\datums\interactions\interaction_definitions.dm"
@@ -3647,6 +3648,7 @@
#include "sandcode\code\game\mecha\mecha_parts.dm"
#include "sandcode\code\game\objects\effects\contraband.dm"
#include "sandcode\code\game\objects\items\airlock_painter.dm"
+#include "sandcode\code\game\objects\items\borg_shapeshifter.dm"
#include "sandcode\code\game\objects\items\BSRPD.dm"
#include "sandcode\code\game\objects\items\cards_ids.dm"
#include "sandcode\code\game\objects\items\chrono_eraser.dm"
@@ -3658,8 +3660,12 @@
#include "sandcode\code\game\objects\items\plushes\goat_boss.dm"
#include "sandcode\code\game\objects\items\plushes\plushes.dm"
#include "sandcode\code\game\objects\items\robot\robot_upgrades.dm"
+#include "sandcode\code\game\objects\items\stacks\sheets\glass.dm"
+#include "sandcode\code\game\objects\items\stacks\sheets\mineral.dm"
+#include "sandcode\code\game\objects\items\stacks\sheets\sheet_types.dm"
#include "sandcode\code\game\objects\items\storage\backpack.dm"
#include "sandcode\code\game\objects\items\storage\bags.dm"
+#include "sandcode\code\game\objects\structures\ghost_role_spawners.dm"
#include "sandcode\code\game\objects\structures\ladders.dm"
#include "sandcode\code\game\objects\structures\lavaland\necropolis_tendril.dm"
#include "sandcode\code\game\turfs\simulated\floor\asteroid.dm"
@@ -3699,6 +3705,8 @@
#include "sandcode\code\modules\mob\living\carbon\show.dm"
#include "sandcode\code\modules\mob\living\carbon\human\human.dm"
#include "sandcode\code\modules\mob\living\silicon\silicon.dm"
+#include "sandcode\code\modules\mob\living\silicon\robot\robot.dm"
+#include "sandcode\code\modules\mob\living\silicon\robot\robot_modules.dm"
#include "sandcode\code\modules\mob\living\simple_animal\friendly\doges.dm"
#include "sandcode\code\modules\mob\living\simple_animal\hostile\megafauna\blood_drunk_miner.dm"
#include "sandcode\code\modules\mob\living\simple_animal\hostile\megafauna\bubblegum.dm"
@@ -3741,6 +3749,7 @@
#include "sandcode\code\modules\reagents\chemistry\recipes\drugs.dm"
#include "sandcode\code\modules\reagents\chemistry\recipes\fermi.dm"
#include "sandcode\code\modules\reagents\chemistry\recipes\others.dm"
+#include "sandcode\code\modules\reagents\reagent_containers\borghydro.dm"
#include "sandcode\code\modules\reagents\reagent_containers\bottle.dm"
#include "sandcode\code\modules\reagents\reagent_containers\spray.dm"
#include "sandcode\code\modules\research\designs\autolathe_designs.dm"
@@ -3760,6 +3769,7 @@
#include "sandcode\code\modules\ruins\lavalandruin_code\doom.dm"
#include "sandcode\code\modules\ruins\lavalandruin_code\kinggoat.dm"
#include "sandcode\code\modules\ruins\lavalandruin_code\misc.dm"
+#include "sandcode\code\modules\ruins\spaceruin_code\hilbertshotel.dm"
#include "sandcode\code\modules\shuttle\spaceship_navigation_beacon.dm"
#include "sandcode\code\modules\spells\spell.dm"
#include "sandcode\code\modules\spells\spell_types\shapeshift.dm"