diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm
index d63d49e8d76..213fe57b90e 100644
--- a/code/_onclick/cyborg.dm
+++ b/code/_onclick/cyborg.dm
@@ -60,6 +60,8 @@
// Cyborgs have no range-checking unless there is item use
if(!W)
+ if(bolt && !bolt.malfunction && A.loc != module)
+ return
A.add_hiddenprint(src)
A.attack_robot(src)
return
@@ -120,35 +122,56 @@
/atom/proc/BorgCtrlShiftClick(var/mob/living/silicon/robot/user) //forward to human click if not overriden
CtrlShiftClick(user)
-/obj/machinery/door/airlock/BorgCtrlShiftClick(mob/user)
+/obj/machinery/door/airlock/BorgCtrlShiftClick(var/mob/living/silicon/robot/user)
+ if(user.bolt && !user.bolt.malfunction)
+ return
+
AICtrlShiftClick(user)
/atom/proc/BorgShiftClick(var/mob/living/silicon/robot/user) //forward to human click if not overriden
ShiftClick(user)
-/obj/machinery/door/airlock/BorgShiftClick(mob/user) // Opens and closes doors! Forwards to AI code.
+/obj/machinery/door/airlock/BorgShiftClick(var/mob/living/silicon/robot/user) // Opens and closes doors! Forwards to AI code.
+ if(user.bolt && !user.bolt.malfunction)
+ return
+
AIShiftClick(user)
/atom/proc/BorgCtrlClick(var/mob/living/silicon/robot/user) //forward to human click if not overriden
CtrlClick(user)
-/obj/machinery/door/airlock/BorgCtrlClick(mob/user) // Bolts doors. Forwards to AI code.
+/obj/machinery/door/airlock/BorgCtrlClick(var/mob/living/silicon/robot/user) // Bolts doors. Forwards to AI code.
+ if(user.bolt && !user.bolt.malfunction)
+ return
+
AICtrlClick(user)
-/obj/machinery/power/apc/BorgCtrlClick(mob/user) // turns off/on APCs. Forwards to AI code.
+/obj/machinery/power/apc/BorgCtrlClick(var/mob/living/silicon/robot/user) // turns off/on APCs. Forwards to AI code.
+ if(user.bolt && !user.bolt.malfunction)
+ return
+
AICtrlClick(user)
-/obj/machinery/turretid/BorgCtrlClick(mob/user) //turret control on/off. Forwards to AI code.
+/obj/machinery/turretid/BorgCtrlClick(var/mob/living/silicon/robot/user) //turret control on/off. Forwards to AI code.
+ if(user.bolt && !user.bolt.malfunction)
+ return
+
AICtrlClick(user)
/atom/proc/BorgAltClick(var/mob/living/silicon/robot/user)
AltClick(user)
return
-/obj/machinery/door/airlock/BorgAltClick(mob/user) // Eletrifies doors. Forwards to AI code.
+/obj/machinery/door/airlock/BorgAltClick(var/mob/living/silicon/robot/user) // Eletrifies doors. Forwards to AI code.
+ if(user.bolt && !user.bolt.malfunction)
+ return
+
AIAltClick(user)
-/obj/machinery/turretid/BorgAltClick(mob/user) //turret lethal on/off. Forwards to AI code.
+/obj/machinery/turretid/BorgAltClick(var/mob/living/silicon/robot/user) //turret lethal on/off. Forwards to AI code.
+ if(user.bolt && !user.bolt.malfunction)
+ return
+
AIAltClick(user)
/*
diff --git a/code/datums/supplypacks/robotics.dm b/code/datums/supplypacks/robotics.dm
index 5f8cf6337c8..1928ee7db68 100644
--- a/code/datums/supplypacks/robotics.dm
+++ b/code/datums/supplypacks/robotics.dm
@@ -189,6 +189,17 @@
containername = "Jumper kit crate"
access = access_robotics
+/datum/supply_pack/robotics/restrainingbolt
+ name = "Restraining bolt crate"
+ contains = list(
+ /obj/item/weapon/implanter = 1,
+ /obj/item/weapon/implantcase/restrainingbolt = 2
+ )
+ cost = 40
+ containertype = /obj/structure/closet/crate/secure/cybersolutions
+ containername = "Restraining bolt crate"
+ access = access_robotics
+
/datum/supply_pack/robotics/bike
name = "Spacebike Crate"
contains = list()
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 014efcb5813..39d54ef96d5 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -862,14 +862,14 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/tgui_data(mob/user)
var/list/data = list()
-
+
var/list/power = list()
power["main"] = main_power_lost_until > 0 ? 0 : 2
power["main_timeleft"] = round(main_power_lost_until > 0 ? max(main_power_lost_until - world.time, 0) / 10 : main_power_lost_until, 1)
power["backup"] = backup_power_lost_until > 0 ? 0 : 2
power["backup_timeleft"] = round(backup_power_lost_until > 0 ? max(backup_power_lost_until - world.time, 0) / 10 : backup_power_lost_until, 1)
data["power"] = power
-
+
data["shock"] = (electrified_until == 0) ? 2 : 0
data["shock_timeleft"] = round(electrified_until > 0 ? max(electrified_until - world.time, 0) / 10 : electrified_until, 1)
data["id_scanner"] = !aiDisabledIdScanner
diff --git a/code/game/objects/items/weapons/implants/implantcase.dm b/code/game/objects/items/weapons/implants/implantcase.dm
index c4040890283..9162be15eb5 100644
--- a/code/game/objects/items/weapons/implants/implantcase.dm
+++ b/code/game/objects/items/weapons/implants/implantcase.dm
@@ -299,3 +299,13 @@
src.imp = new /obj/item/weapon/implant/organ/limbaugment/wrist/blade( src )
..()
return
+
+/obj/item/weapon/implantcase/restrainingbolt
+ name = "glass case - 'Restraining Bolt'"
+ desc = "A case containing a restraining bolt."
+ icon_state = "implantcase-b"
+
+/obj/item/weapon/implantcase/restrainingbolt/New()
+ src.imp = new /obj/item/weapon/implant/restrainingbolt( src )
+ ..()
+ return
diff --git a/code/game/objects/items/weapons/implants/implanter.dm b/code/game/objects/items/weapons/implants/implanter.dm
index c1b0d5db8dd..adb79364dcd 100644
--- a/code/game/objects/items/weapons/implants/implanter.dm
+++ b/code/game/objects/items/weapons/implants/implanter.dm
@@ -150,3 +150,12 @@
S.remove_from_storage(A)
A.loc.contents.Remove(A)
update()
+
+/obj/item/weapon/implanter/restrainingbolt
+ name = "implanter (bolt)"
+
+/obj/item/weapon/implanter/restrainingbolt/New()
+ src.imp = new /obj/item/weapon/implant/restrainingbolt( src )
+ ..()
+ update()
+ return
diff --git a/code/game/objects/items/weapons/implants/implantrestrainingbolt.dm b/code/game/objects/items/weapons/implants/implantrestrainingbolt.dm
new file mode 100644
index 00000000000..7f4a562297c
--- /dev/null
+++ b/code/game/objects/items/weapons/implants/implantrestrainingbolt.dm
@@ -0,0 +1,5 @@
+
+/obj/item/weapon/implant/restrainingbolt
+ name = "\improper restraining bolt"
+ icon = 'icons/obj/device.dmi'
+ icon_state = "implant"
diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm
index 7494867d2d8..435ca993546 100644
--- a/code/modules/mob/living/carbon/human/human_helpers.dm
+++ b/code/modules/mob/living/carbon/human/human_helpers.dm
@@ -208,6 +208,20 @@
plane_holder.set_vis(vis,FALSE)
vis_enabled -= vis
+/mob/living/carbon/human/get_restraining_bolt()
+ var/obj/item/weapon/implant/restrainingbolt/RB
+
+ for(var/obj/item/organ/external/EX in organs)
+ RB = locate() in EX
+ if(istype(RB) && !(RB.malfunction))
+ break
+
+ if(RB)
+ if(!RB.malfunction)
+ return TRUE
+
+ return FALSE
+
#undef HUMAN_EATING_NO_ISSUE
#undef HUMAN_EATING_NO_MOUTH
#undef HUMAN_EATING_BLOCKED_MOUTH
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 5c56b8a4482..7debf735b1c 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -700,6 +700,14 @@
/mob/living/proc/has_eyes()
return 1
+/mob/living/proc/get_restraining_bolt()
+ var/obj/item/weapon/implant/restrainingbolt/RB = locate() in src
+ if(RB)
+ if(!RB.malfunction)
+ return TRUE
+
+ return FALSE
+
/mob/living/proc/slip(var/slipped_on,stun_duration=8)
return 0
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 7d67ca3cc32..849696ea4c5 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -91,6 +91,8 @@
var/tracking_entities = 0 //The number of known entities currently accessing the internal camera
var/braintype = "Cyborg"
+ var/obj/item/weapon/implant/restrainingbolt/bolt // The restraining bolt installed into the cyborg.
+
var/list/robot_verbs_default = list(
/mob/living/silicon/robot/proc/sensor_mode,
/mob/living/silicon/robot/proc/robot_checklaws
@@ -481,6 +483,20 @@
return
+ if(istype(W, /obj/item/weapon/implant/restrainingbolt) && !cell)
+ if(bolt)
+ to_chat(user, "There is already a restraining bolt installed in this cyborg.")
+ return
+
+ else
+ user.drop_from_inventory(W)
+ W.forceMove(src)
+ bolt = W
+
+ to_chat(user, "You install \the [W].")
+
+ return
+
if(istype(W, /obj/item/weapon/aiModule)) // Trying to modify laws locally.
if(!opened)
to_chat(user, "You need to open \the [src]'s panel before you can modify them.")
@@ -622,6 +638,21 @@
to_chat(user, "Unable to locate a radio.")
updateicon()
+ else if(W.is_wrench() && opened && !cell)
+ if(bolt)
+ to_chat(user,"You begin removing \the [bolt].")
+
+ if(do_after(user, 2 SECONDS, src))
+ bolt.forceMove(get_turf(src))
+ bolt = null
+
+ to_chat(user, "You remove \the [bolt].")
+
+ else
+ to_chat(user, "There is no restraining bolt installed.")
+
+ return
+
else if(istype(W, /obj/item/device/encryptionkey/) && opened)
if(radio)//sanityyyyyy
radio.attackby(W,user)//GTFO, you have your own procs
@@ -664,6 +695,30 @@
spark_system.start()
return ..()
+/mob/living/silicon/robot/GetIdCard()
+ if(bolt && !bolt.malfunction)
+ return null
+ return idcard
+
+/mob/living/silicon/robot/get_restraining_bolt()
+ var/obj/item/weapon/implant/restrainingbolt/RB = bolt
+
+ if(istype(RB))
+ if(!RB.malfunction)
+ return TRUE
+
+ return FALSE
+
+/mob/living/silicon/robot/resist_restraints()
+ if(bolt)
+ if(!bolt.malfunction)
+ visible_message("[src] is trying to break their [bolt]!", "You attempt to break your [bolt]. (This will take around 90 seconds and you need to stand still)")
+ if(do_after(src, 1.5 MINUTES, src, incapacitation_flags = INCAPACITATION_DISABLED))
+ visible_message("[src] manages to break \the [bolt]!", "You successfully break your [bolt].")
+ bolt.malfunction = MALFUNCTION_PERMANENT
+
+ return
+
/mob/living/silicon/robot/proc/module_reset()
transform_with_anim() //VOREStation edit: sprite animation
uneq_all()
@@ -1015,6 +1070,9 @@
return 0
/mob/living/silicon/robot/binarycheck()
+ if(get_restraining_bolt())
+ return FALSE
+
if(is_component_functioning("comms"))
var/datum/robot_component/RC = get_component("comms")
use_power(RC.active_usage)
@@ -1107,6 +1165,11 @@
sleep(20)
to_chat(src, "SynBorg v1.7.1 loaded.")
sleep(5)
+ if(bolt)
+ if(!bolt.malfunction)
+ bolt.malfunction = MALFUNCTION_PERMANENT
+ to_chat(src, "RESTRAINING BOLT DISABLED")
+ sleep(5)
to_chat(src, "LAW SYNCHRONISATION ERROR")
sleep(5)
to_chat(src, "Would you like to send a report to NanoTraSoft? Y/N")
diff --git a/code/modules/mob/living/silicon/robot/robot_movement.dm b/code/modules/mob/living/silicon/robot/robot_movement.dm
index bc9b7367f2c..7a733f002bd 100644
--- a/code/modules/mob/living/silicon/robot/robot_movement.dm
+++ b/code/modules/mob/living/silicon/robot/robot_movement.dm
@@ -32,6 +32,9 @@
if(module_active && istype(module_active,/obj/item/borg/combat/mobility))
. -= 2 // VOREStation Edit
+ if(get_restraining_bolt()) // Borgs with Restraining Bolts move slower.
+ . += 1
+
. += config.robot_delay
. += ..()
diff --git a/code/modules/organs/internal/augment.dm b/code/modules/organs/internal/augment.dm
index bb899e5c2ba..831d9d3b893 100644
--- a/code/modules/organs/internal/augment.dm
+++ b/code/modules/organs/internal/augment.dm
@@ -64,6 +64,10 @@
else
return
+ if(robotic && owner.get_restraining_bolt())
+ to_chat(owner, "\The [src] doesn't respond.")
+ return
+
var/item_to_equip = integrated_object
if(!item_to_equip && integrated_object_type)
item_to_equip = integrated_object_type
diff --git a/code/modules/organs/internal/augment/armmounted.dm b/code/modules/organs/internal/augment/armmounted.dm
index 833d4be435d..c22988de836 100644
--- a/code/modules/organs/internal/augment/armmounted.dm
+++ b/code/modules/organs/internal/augment/armmounted.dm
@@ -143,7 +143,7 @@
if(istype(owner, /mob/living/carbon/human))
var/mob/living/carbon/human/H = owner
H.add_modifier(/datum/modifier/melee_surge, 0.75 MINUTES)
-
+
/obj/item/organ/internal/augment/armmounted/shoulder/blade
name = "armblade implant"
desc = "A large implant that fits into a subject's arm. It deploys a large metal blade by some painful means."
diff --git a/vorestation.dme b/vorestation.dme
index 6692d493378..1aa3b9060b7 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -1321,7 +1321,11 @@
#include "code\game\objects\items\weapons\implants\implantfreedom.dm"
#include "code\game\objects\items\weapons\implants\implantlanguage.dm"
#include "code\game\objects\items\weapons\implants\implantpad.dm"
+<<<<<<< HEAD:vorestation.dme
#include "code\game\objects\items\weapons\implants\implantreagent_vr.dm"
+=======
+#include "code\game\objects\items\weapons\implants\implantrestrainingbolt.dm"
+>>>>>>> 8dc0404... Adds the Restraining Bolt. (#7820):polaris.dme
#include "code\game\objects\items\weapons\implants\implantuplink.dm"
#include "code\game\objects\items\weapons\implants\neuralbasic.dm"
#include "code\game\objects\items\weapons\material\ashtray.dm"