diff --git a/code/game/machinery/vending/vendor_types/crew/synthetic.dm b/code/game/machinery/vending/vendor_types/crew/synthetic.dm
index 240155176efa..0c5b32af39ad 100644
--- a/code/game/machinery/vending/vendor_types/crew/synthetic.dm
+++ b/code/game/machinery/vending/vendor_types/crew/synthetic.dm
@@ -87,9 +87,17 @@
//------------CLOTHING VENDOR---------------
GLOBAL_LIST_INIT(cm_vending_clothing_synth, list(
- list("EXPERIMENTAL TOOL TOKEN (TAKE ALL)", 0, null, null, null),
+ list("EXPERIMENTAL TOOL TOKEN", 0, null, null, null),
list("Experimental Tool Vendor Token", 0, /obj/item/coin/marine/synth, MARINE_CAN_BUY_ESSENTIALS, VENDOR_ITEM_MANDATORY),
+ list("SYNTHETIC SPECIALTY EQUIPMENT", 0, null, null, null),
+ list("PK-130 SIMI Wrist-Mounted Computer", 0, /obj/item/clothing/gloves/synth, MARINE_CAN_BUY_KIT, VENDOR_ITEM_REGULAR),
+ list("Smartpack, Blue", 0, /obj/item/storage/backpack/marine/smartpack, MARINE_CAN_BUY_KIT, VENDOR_ITEM_REGULAR),
+ list("Smartpack, Green", 0, /obj/item/storage/backpack/marine/smartpack/green, MARINE_CAN_BUY_KIT, VENDOR_ITEM_REGULAR),
+ list("Smartpack, Tan", 0, /obj/item/storage/backpack/marine/smartpack/tan, MARINE_CAN_BUY_KIT, VENDOR_ITEM_REGULAR),
+ list("Smartpack, White", 0, /obj/item/storage/backpack/marine/smartpack/white, MARINE_CAN_BUY_KIT, VENDOR_ITEM_REGULAR),
+ list("Smartpack, Black", 0, /obj/item/storage/backpack/marine/smartpack/black, MARINE_CAN_BUY_KIT, VENDOR_ITEM_REGULAR),
+
list("RADIO (TAKE ALL)", 0, null, null, null),
list("Headset", 0, /obj/item/device/radio/headset/almayer/mcom/synth, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY),
@@ -134,11 +142,6 @@ GLOBAL_LIST_INIT(cm_vending_clothing_synth, list(
list("Latex Gloves", 0, /obj/item/clothing/gloves/latex, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_REGULAR),
list("BACKPACK (CHOOSE 1)", 0, null, null, null),
- list("Smartpack, Blue", 0, /obj/item/storage/backpack/marine/smartpack, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR),
- list("Smartpack, Green", 0, /obj/item/storage/backpack/marine/smartpack/green, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR),
- list("Smartpack, Tan", 0, /obj/item/storage/backpack/marine/smartpack/tan, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR),
- list("Smartpack, White", 0, /obj/item/storage/backpack/marine/smartpack/white, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR),
- list("Smartpack, Black", 0, /obj/item/storage/backpack/marine/smartpack/black, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR),
list("Logistics IMP Backpack", 0, /obj/item/storage/backpack/marine/satchel/big, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR),
list("Expedition Chestrig", 0, /obj/item/storage/backpack/marine/satchel/intel/chestrig, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR),
@@ -338,6 +341,7 @@ GLOBAL_LIST_INIT(cm_vending_clothing_synth_snowflake, list(
list("Backpack, USCM Medical", 12, /obj/item/storage/backpack/marine/medic, null, VENDOR_ITEM_REGULAR),
list("Chestrig, Technician", 12, /obj/item/storage/backpack/marine/satchel/tech, null, VENDOR_ITEM_REGULAR),
list("Satchel, USCM", 12, /obj/item/storage/backpack/marine/satchel, null, VENDOR_ITEM_REGULAR),
+ list("Satchel, USCM Medical", 12, /obj/item/storage/backpack/marine/satchel/medic, null, VENDOR_ITEM_REGULAR),
list("Satchel, Leather", 12, /obj/item/storage/backpack/satchel, null, VENDOR_ITEM_REGULAR),
list("Satchel, Medical", 12, /obj/item/storage/backpack/satchel/med, null, VENDOR_ITEM_REGULAR),
list("USCM RTO Pack", 12, /obj/item/storage/backpack/marine/satchel/rto, null, VENDOR_ITEM_REGULAR),
@@ -401,16 +405,27 @@ GLOBAL_LIST_INIT(cm_vending_clothing_synth_snowflake, list(
return GLOB.cm_vending_synth_tools
GLOBAL_LIST_INIT(cm_vending_synth_tools, list(
- list("Autocompressor", 15, /obj/item/clothing/suit/auto_cpr, null, VENDOR_ITEM_REGULAR),
+ list("PK-130", 0, null, null, null),
+ list("PK-130 Repair Mode", 7, /obj/item/device/simi_chip/repair, null, VENDOR_ITEM_RECOMMENDED),
+ list("PK-130 Protection Mode", 7, /obj/item/device/simi_chip/protect, null, VENDOR_ITEM_REGULAR),
+ list("PK-130 Anchor Mode", 4, /obj/item/device/simi_chip/anchor, null, VENDOR_ITEM_REGULAR),
+ list("PK-130 Motion Detector", 4, /obj/item/device/simi_chip/motion_detector, null, VENDOR_ITEM_REGULAR),
+
+ list("UTILITY & SELF DEFENSE TOOLS", 0, null, null, null),
+ list("Telescopic Baton", 15, /obj/item/weapon/telebaton, null, VENDOR_ITEM_REGULAR),
+ list("Experimental Meson Goggles", 15, /obj/item/clothing/glasses/night/experimental_mesons, null, VENDOR_ITEM_REGULAR),
list("Backpack Firefighting Watertank", 15, /obj/item/reagent_container/glass/watertank/atmos, null, VENDOR_ITEM_REGULAR),
- list("Breaching Hammer", 15, /obj/item/weapon/twohanded/breacher/synth, null, VENDOR_ITEM_REGULAR),
+
+ list("MEDICAL TOOLS", 0, null, null, null),
+ list("Autocompressor", 15, /obj/item/clothing/suit/auto_cpr, null, VENDOR_ITEM_REGULAR),
list("Compact Defibrillator", 15, /obj/item/device/defibrillator/compact, null, VENDOR_ITEM_REGULAR),
- list("Compact Nailgun kit", 15, /obj/effect/essentials_set/cnailgun, null, VENDOR_ITEM_REGULAR),
+ list("Portable Dialysis Machine", 15, /obj/item/tool/portadialysis, null, VENDOR_ITEM_REGULAR),
list("Crew Monitor", 15, /obj/item/tool/crew_monitor, null, VENDOR_ITEM_REGULAR),
- list("Experimental Meson Goggles", 15, /obj/item/clothing/glasses/night/experimental_mesons, null, VENDOR_ITEM_REGULAR),
+
+ list("CONSTRUCTION TOOLS", 0, null, null, null),
+ list("Breaching Hammer", 15, /obj/item/weapon/twohanded/breacher/synth, null, VENDOR_ITEM_REGULAR),
+ list("Compact Nailgun kit", 15, /obj/effect/essentials_set/cnailgun, null, VENDOR_ITEM_REGULAR),
list("Maintenance Jack", 15, /obj/item/maintenance_jack, null, VENDOR_ITEM_REGULAR),
- list("Portable Dialysis Machine", 15, /obj/item/tool/portadialysis, null, VENDOR_ITEM_REGULAR),
- list("Telescopic Baton", 15, /obj/item/weapon/telebaton, null, VENDOR_ITEM_REGULAR),
))
//------------EXPERIMENTAL TOOL KITS---------------
diff --git a/code/game/objects/items/devices/motion_detector.dm b/code/game/objects/items/devices/motion_detector.dm
index f68295001f92..6a5ab8a32d23 100644
--- a/code/game/objects/items/devices/motion_detector.dm
+++ b/code/game/objects/items/devices/motion_detector.dm
@@ -184,9 +184,11 @@
if(ishuman(loc))
return loc
-/obj/item/device/motiondetector/sg
+/obj/item/device/motiondetector/integrated
+ name = "integrated motion detector"
+ desc = "A motion sensing component from another device."
-/obj/item/device/motiondetector/sg/get_user()
+/obj/item/device/motiondetector/integrated/get_user()
var/atom/A = loc
if(ishuman(A.loc))
return A.loc
diff --git a/code/game/objects/items/tools/synth_bracer/_defines.dm b/code/game/objects/items/tools/synth_bracer/_defines.dm
new file mode 100644
index 000000000000..1a4d4bcdf531
--- /dev/null
+++ b/code/game/objects/items/tools/synth_bracer/_defines.dm
@@ -0,0 +1,44 @@
+// Possible Bracer Colors
+#define SIMI_COLOR_DEFAULT "default"
+#define SIMI_COLOR_WHITE "white"
+
+/// Loads/Reloads the available actions on the computer itself.
+#define SIMI_ACTIONS_LOAD "load"
+#define SIMI_ACTIONS_RELOAD "reload"
+/// Cleans and then adds actions to the user.
+#define SIMI_ACTIONS_ADD "add"
+/// Removes actions from the user.
+#define SIMI_ACTIONS_REMOVE "remove"
+
+/// No active module.
+#define SIMI_ACTIVE_NONE "none"
+
+// Primary Abilities
+#define SIMI_PRIMARY_ACTION "primary"
+
+/// Synth self-repair
+#define SIMI_ABILITY_REPAIR "repair"
+#define SIMI_REPAIR_COST 50
+
+/// Synth fortify, enforced stationary
+#define SIMI_ABILITY_ANCHOR "anchor"
+#define SIMI_IMMOBILE_COST 20
+
+/// Damage reduced but incapable of self defense.
+#define SIMI_ABILITY_PROTECT "protect"
+#define SIMI_PROTECTIVE_COST 60
+
+// Secondary Abilities
+#define SIMI_SECONDARY_ACTION "secondary"
+
+/// Rescue hook.
+#define SIMI_SECONDARY_HOOK "hook"
+/// Motion Detector
+#define SIMI_SECONDARY_MD "motion"
+
+// Statuses
+#define SIMI_STATUS_IDLE "status_idle"
+#define SIMI_STATUS_NOACCESS "status_unauthorized"
+#define SIMI_STATUS_LOWPOWER "status_lowbattery"
+#define SIMI_STATUS_NOPOWER "status_nobattery"
+#define SIMI_STATUS_CHARGING "status_charging"
diff --git a/code/game/objects/items/tools/synth_bracer/abilities/chips.dm b/code/game/objects/items/tools/synth_bracer/abilities/chips.dm
new file mode 100644
index 000000000000..305aa3802abc
--- /dev/null
+++ b/code/game/objects/items/tools/synth_bracer/abilities/chips.dm
@@ -0,0 +1,34 @@
+/obj/item/device/simi_chip
+ name = "PK-130 SIMI programmable circuit (NOT FOR USE)"
+ desc = "A programmable computer circuit used within the PK-130 SINI wrist-mounted computer to add or unlock various functions."
+ icon = 'icons/obj/items/synth/bracer.dmi'
+ icon_state = "simi_chip_white"
+
+ /// The action this chip will add to the SIMI
+ var/chip_action = /datum/action/human_action
+ /// If this chip is 'secret' or not (cannot be removed/one time use)
+ var/secret = FALSE
+
+/obj/item/device/simi_chip/repair
+ name = "PK-130 SIMI programmable circuit (Self-Repair)"
+ chip_action = /datum/action/human_action/synth_bracer/repair_form
+ icon_state = "simi_chip_red"
+
+/obj/item/device/simi_chip/protect
+ name = "PK-130 SIMI programmable circuit (Damage Bracing)"
+ icon_state = "simi_chip_blue"
+ chip_action = /datum/action/human_action/synth_bracer/protective_form
+
+/obj/item/device/simi_chip/anchor
+ name = "PK-130 SIMI programmable circuit (Anchor)"
+ icon_state = "simi_chip_blue"
+ chip_action = /datum/action/human_action/synth_bracer/anchor_form
+
+/obj/item/device/simi_chip/rescue_hook
+ name = "PK-130 SIMI programmable circuit (Rescue Hook)"
+ chip_action = /datum/action/human_action/activable/synth_bracer/rescue_hook
+
+/obj/item/device/simi_chip/motion_detector
+ name = "PK-130 SIMI programmable circuit (Motion Detector)"
+ chip_action = /datum/action/human_action/synth_bracer/motion_detector
+ desc = "A programmable computer circuit used within the PK-130 SINI wrist-mounted computer to add or unlock various functions. This one activates a motion detector capability, at a running cost of power."
diff --git a/code/game/objects/items/tools/synth_bracer/abilities/framework.dm b/code/game/objects/items/tools/synth_bracer/abilities/framework.dm
new file mode 100644
index 000000000000..7d85be000650
--- /dev/null
+++ b/code/game/objects/items/tools/synth_bracer/abilities/framework.dm
@@ -0,0 +1,225 @@
+/* -- ACTIVATABLE ACTIONS -- */
+
+/datum/action/human_action/activable/synth_bracer
+ icon_file = 'icons/obj/items/synth/bracer.dmi'
+ var/mob/living/carbon/human/synth
+ var/obj/item/clothing/gloves/synth/synth_bracer
+ var/charge_cost = 0
+ var/handles_cooldown = FALSE
+ var/handles_charge_cost = FALSE
+ /// What cateogry of action it is. Can only have one active action from each type.
+ var/category = SIMI_SECONDARY_ACTION
+ var/human_adaptable = FALSE
+ /// The tag to tell what ability is active.
+ var/ability_tag = SIMI_ACTIVE_NONE
+
+/datum/action/human_action/activable/synth_bracer/give_to(user)
+ /// never add a check to see if the synth has gloves on, because they shouldn't have these abilities while not wearing gloves. it should runtime to let us know
+ synth = user
+ synth_bracer = synth.gloves
+ if(!issynth(user) && !is_human_usable())
+ synth = null
+ synth_bracer = null
+ return FALSE
+ return ..()
+
+/datum/action/human_action/activable/synth_bracer/remove_from(mob/living/carbon/human/H)
+ synth = null
+ synth_bracer = null
+ return ..()
+
+/datum/action/human_action/activable/synth_bracer/Destroy()
+ synth = null
+ synth_bracer = null
+ return ..()
+
+/datum/action/human_action/activable/synth_bracer/action_activate()
+ if(is_active())
+ set_inactive(category)
+ return
+ ..()
+
+/datum/action/human_action/activable/synth_bracer/use_ability(mob/M)
+ if(!can_use_action())
+ return FALSE
+ if(synth_bracer.battery_charge < charge_cost)
+ to_chat(synth, SPAN_WARNING("You don't have enough charge to to do this! Charge: [synth_bracer.battery_charge]/[synth_bracer.battery_charge_max] you need [SPAN_RED(charge_cost)]."))
+ return FALSE
+ if(!handles_cooldown && cooldown)
+ enter_cooldown()
+ if(!handles_charge_cost && charge_cost)
+ synth_bracer.drain_charge(owner, charge_cost)
+ return TRUE
+
+/datum/action/human_action/activable/synth_bracer/can_use_action()
+ if(is_active())
+ set_inactive(category)
+ return FALSE
+ if(!issynth(owner) && !is_human_usable())
+ to_chat(owner, SPAN_WARNING("You have no idea how to use this!"))
+ if(owner.is_mob_incapacitated())
+ to_chat(owner, SPAN_WARNING("You cannot use this action while incapacitated!"))
+ return FALSE
+
+ switch(category)
+ if(SIMI_PRIMARY_ACTION)
+ if(synth_bracer.active_ability != SIMI_ACTIVE_NONE)
+ to_chat(owner, SPAN_WARNING("You cannot use this action while another primary ability is active."))
+ return FALSE
+ if(SIMI_SECONDARY_ACTION)
+ if(synth_bracer.active_utility != SIMI_ACTIVE_NONE)
+ to_chat(owner, SPAN_WARNING("You cannot use this action while another secondary ability is active."))
+ return FALSE
+
+ if(synth_bracer.battery_charge <= 0)
+ to_chat(synth, SPAN_WARNING("You cannot do this without power!"))
+ return FALSE
+ if(synth_bracer.battery_charge < charge_cost)
+ to_chat(synth, SPAN_WARNING("You don't have enough charge to to do this! Charge: [synth_bracer.battery_charge]/[synth_bracer.battery_charge_max] you need [SPAN_RED(charge_cost)]."))
+ return FALSE
+ if(!action_cooldown_check())
+ return FALSE
+ return ..()
+
+/datum/action/human_action/activable/synth_bracer/proc/is_human_usable()
+ if(human_adaptable && synth_bracer.human_adapted)
+ return TRUE
+ return FALSE
+
+/datum/action/human_action/activable/synth_bracer/proc/set_active(category = SIMI_SECONDARY_ACTION, set_ability = SIMI_ACTIVE_NONE)
+ switch(category)
+ if(SIMI_PRIMARY_ACTION)
+ synth_bracer.active_ability = set_ability
+ if(SIMI_SECONDARY_ACTION)
+ synth_bracer.active_utility = set_ability
+ if((synth_bracer.active_ability == SIMI_ACTIVE_NONE) && (synth_bracer.active_utility == SIMI_ACTIVE_NONE))
+ synth_bracer.flags_item &= ~NODROP
+ else
+ synth_bracer.flags_item |= NODROP
+ synth_bracer.update_icon(synth)
+
+/datum/action/human_action/activable/synth_bracer/proc/set_inactive(category = SIMI_SECONDARY_ACTION)
+ set_active(category, SIMI_ACTIVE_NONE)
+
+/datum/action/human_action/activable/synth_bracer/proc/is_active()
+ switch(category)
+ if(SIMI_PRIMARY_ACTION)
+ if(synth_bracer.active_ability == ability_tag)
+ return TRUE
+ if(SIMI_SECONDARY_ACTION)
+ if(synth_bracer.active_utility == ability_tag)
+ return TRUE
+ return FALSE
+/* -- ON-CLICK ACTIONS -- */
+
+/datum/action/human_action/synth_bracer
+ icon_file = 'icons/obj/items/synth/bracer.dmi'
+ var/mob/living/carbon/human/synth
+ var/obj/item/clothing/gloves/synth/synth_bracer
+ var/ability_used_time = 0
+ var/charge_cost = 0
+ var/handles_cooldown = FALSE // whether the cooldown gets handled by the child, or should be done automatically here
+ var/handles_charge_cost = FALSE
+ /// What cateogry of action it is. Can only have one active action from each type.
+ var/category = SIMI_SECONDARY_ACTION
+ var/human_adaptable = FALSE
+ /// The tag to tell what ability is active.
+ var/ability_tag = SIMI_ACTIVE_NONE
+
+/datum/action/human_action/synth_bracer/give_to(user)
+ synth = user
+ synth_bracer = synth.gloves
+ if(!issynth(user) && !is_human_usable())
+ synth = null
+ synth_bracer = null
+ return FALSE
+ return ..()
+
+/datum/action/human_action/synth_bracer/remove_from(user)
+ synth = null
+ synth_bracer = null
+ return ..()
+
+/datum/action/human_action/synth_bracer/Destroy()
+ synth = null
+ synth_bracer = null
+ return ..()
+
+/datum/action/human_action/synth_bracer/proc/form_call()
+ return
+
+/datum/action/human_action/synth_bracer/action_cooldown_check()
+ return ability_used_time <= world.time
+
+/datum/action/human_action/synth_bracer/proc/enter_cooldown(amount = cooldown)
+ ability_used_time = world.time + amount
+ update_button_icon()
+ addtimer(CALLBACK(src, PROC_REF(update_button_icon)), amount)
+
+/datum/action/human_action/synth_bracer/update_button_icon()
+ if(!button)
+ return
+ if(!action_cooldown_check())
+ button.color = rgb(240,180,0,200)
+ else
+ button.color = rgb(255,255,255,255)
+
+/datum/action/human_action/synth_bracer/can_use_action()
+ if(!issynth(owner) && !is_human_usable())
+ to_chat(owner, SPAN_WARNING("You have no idea how to use this!"))
+ if(owner.is_mob_incapacitated())
+ to_chat(owner, SPAN_WARNING("You cannot use this action while incapacitated!"))
+ return FALSE
+
+ switch(category)
+ if(SIMI_PRIMARY_ACTION)
+ if(synth_bracer.active_ability != SIMI_ACTIVE_NONE)
+ to_chat(owner, SPAN_WARNING("You cannot use this action while another primary ability is active."))
+ return FALSE
+ if(SIMI_SECONDARY_ACTION)
+ if(synth_bracer.active_utility != SIMI_ACTIVE_NONE)
+ to_chat(owner, SPAN_WARNING("You cannot use this action while another secondary ability is active."))
+ return FALSE
+
+ if(synth_bracer.battery_charge <= 0)
+ to_chat(synth, SPAN_WARNING("You cannot do this without power!"))
+ return FALSE
+ if(synth_bracer.battery_charge < charge_cost)
+ to_chat(synth, SPAN_WARNING("You don't have enough charge to to do this! Charge: [synth_bracer.battery_charge]/[synth_bracer.battery_charge_max] you need [SPAN_RED(charge_cost)]."))
+ return FALSE
+ if(!action_cooldown_check())
+ return FALSE
+ return ..()
+
+/datum/action/human_action/synth_bracer/action_activate()
+ . = ..()
+ if(!istype(owner, /mob/living/carbon/human))
+ return
+ var/mob/living/carbon/human/human_owner = owner
+ if(human_owner.gloves == synth_bracer)
+ form_call(synth_bracer, human_owner)
+ if(!handles_cooldown && cooldown)
+ enter_cooldown()
+ if(!handles_charge_cost && charge_cost)
+ synth_bracer.drain_charge(owner, charge_cost)
+
+/datum/action/human_action/synth_bracer/proc/is_human_usable()
+ if(human_adaptable && synth_bracer.human_adapted)
+ return TRUE
+ return FALSE
+
+/datum/action/human_action/synth_bracer/proc/set_active(category = SIMI_SECONDARY_ACTION, set_ability = SIMI_ACTIVE_NONE)
+ synth_bracer.set_active(category, set_ability)
+
+/datum/action/human_action/synth_bracer/proc/set_inactive(category = SIMI_SECONDARY_ACTION)
+ set_active(category, SIMI_ACTIVE_NONE)
+
+/datum/action/human_action/synth_bracer/proc/is_active()
+ switch(category)
+ if(SIMI_PRIMARY_ACTION)
+ if(synth_bracer.active_ability == ability_tag)
+ return TRUE
+ if(SIMI_SECONDARY_ACTION)
+ if(synth_bracer.active_utility == ability_tag)
+ return TRUE
+ return FALSE
diff --git a/code/game/objects/items/tools/synth_bracer/abilities/integrated/crew_monitor.dm b/code/game/objects/items/tools/synth_bracer/abilities/integrated/crew_monitor.dm
new file mode 100644
index 000000000000..1ed3ec64b4d5
--- /dev/null
+++ b/code/game/objects/items/tools/synth_bracer/abilities/integrated/crew_monitor.dm
@@ -0,0 +1,33 @@
+/datum/action/human_action/synth_bracer/crew_monitor
+ name = "View Crew Monitor"
+ action_icon_state = "crew_monitor"
+
+ var/datum/radar/lifeline/radar
+ human_adaptable = TRUE
+
+/datum/action/human_action/synth_bracer/crew_monitor/New()
+ ..()
+ radar = new /datum/radar/lifeline(src, "UNSET")
+
+/datum/action/human_action/synth_bracer/crew_monitor/give_to(user)
+ ..()
+ if(!synth_bracer)
+ return
+ radar.holder = synth_bracer
+ radar.faction = synth_bracer.faction
+
+/datum/action/human_action/synth_bracer/crew_monitor/remove_from(user)
+ radar.holder = src
+ radar.faction = "UNSET"
+ return ..()
+
+/datum/action/human_action/synth_bracer/crew_monitor/Destroy()
+ QDEL_NULL(radar)
+ return ..()
+
+/datum/action/human_action/synth_bracer/crew_monitor/action_activate()
+ ..()
+ if(COOLDOWN_FINISHED(synth_bracer, sound_cooldown))
+ COOLDOWN_START(synth_bracer, sound_cooldown, 5 SECONDS)
+ playsound(synth_bracer, 'sound/machines/terminal_processing.ogg', 35, TRUE)
+ radar.tgui_interact(usr)
diff --git a/code/game/objects/items/tools/synth_bracer/abilities/integrated/ocular_designator.dm b/code/game/objects/items/tools/synth_bracer/abilities/integrated/ocular_designator.dm
new file mode 100644
index 000000000000..edc749fa56a5
--- /dev/null
+++ b/code/game/objects/items/tools/synth_bracer/abilities/integrated/ocular_designator.dm
@@ -0,0 +1,63 @@
+/obj/item/clothing/gloves/synth
+ var/obj/item/device/binoculars/binos
+
+/obj/item/clothing/gloves/synth/Initialize(mapload, ...)
+ . = ..()
+ binos = new(src)
+ RegisterSignal(binos, COMSIG_ITEM_DROPPED, PROC_REF(return_binos))
+
+/obj/item/clothing/gloves/synth/attackby(obj/item/I, mob/user)
+ if(I == binos)
+ return_binos()
+ return
+ return ..()
+
+/obj/item/clothing/gloves/synth/dropped(mob/user)
+ . = ..()
+ return_binos()
+
+/obj/item/clothing/gloves/synth/Destroy()
+ QDEL_NULL(binos)
+ return ..()
+
+/obj/item/clothing/gloves/synth/proc/deploy_binos(mob/M)
+ if(!M.put_in_active_hand(binos))
+ M.put_in_inactive_hand(binos)
+
+/obj/item/clothing/gloves/synth/proc/return_binos()
+ if(QDELETED(binos))
+ binos = null
+ return
+
+ if(ismob(binos.loc))
+ var/mob/M = binos.loc
+ M.drop_inv_item_to_loc(binos, src)
+ else
+ binos.forceMove(src)
+
+
+/datum/action/human_action/synth_bracer/deploy_binoculars
+ name = "Deploy Binoculars"
+ action_icon_state = "far_sight"
+ human_adaptable = TRUE
+
+/datum/action/human_action/synth_bracer/deploy_ocular_binos/can_use_action()
+ if(QDELETED(synth_bracer.binos) || synth_bracer.binos.loc != synth_bracer)
+ to_chat(synth, SPAN_WARNING("The ocular device isn't inside the SIMI anymore."))
+ return FALSE
+ if(synth.l_hand && synth.r_hand)
+ to_chat(synth, SPAN_WARNING("You need at least one free hand."))
+ return FALSE
+ return ..()
+
+/datum/action/human_action/synth_bracer/deploy_binoculars/action_activate()
+ ..()
+ if(COOLDOWN_FINISHED(synth_bracer, sound_cooldown))
+ COOLDOWN_START(synth_bracer, sound_cooldown, 5 SECONDS)
+ playsound(synth_bracer.loc,'sound/machines/click.ogg', 25, TRUE)
+ if(synth_bracer.binos.loc == synth_bracer)
+ to_chat(synth, SPAN_NOTICE("You deploy your binoculars."))
+ synth_bracer.deploy_binos(synth)
+ else
+ to_chat(synth, SPAN_NOTICE("You return your binoculars."))
+ synth_bracer.return_binos(synth)
diff --git a/code/game/objects/items/tools/synth_bracer/abilities/integrated/tactical_map.dm b/code/game/objects/items/tools/synth_bracer/abilities/integrated/tactical_map.dm
new file mode 100644
index 000000000000..4edf10c5f276
--- /dev/null
+++ b/code/game/objects/items/tools/synth_bracer/abilities/integrated/tactical_map.dm
@@ -0,0 +1,22 @@
+/datum/action/human_action/synth_bracer/tactical_map
+ name = "View Tactical Map"
+ action_icon_state = "minimap"
+
+ var/datum/tacmap/tacmap
+ var/minimap_type = MINIMAP_FLAG_USCM
+ human_adaptable = TRUE
+
+/datum/action/human_action/synth_bracer/tactical_map/New()
+ . = ..()
+ tacmap = new(src, minimap_type)
+
+/datum/action/human_action/synth_bracer/tactical_map/Destroy()
+ QDEL_NULL(tacmap)
+ return ..()
+
+/datum/action/human_action/synth_bracer/tactical_map/action_activate()
+ ..()
+ if(COOLDOWN_FINISHED(synth_bracer, sound_cooldown))
+ COOLDOWN_START(synth_bracer, sound_cooldown, 5 SECONDS)
+ playsound(synth_bracer, 'sound/machines/terminal_processing.ogg', 35, TRUE)
+ tacmap.tgui_interact(usr)
diff --git a/code/game/objects/items/tools/synth_bracer/abilities/primary/anchor_form.dm b/code/game/objects/items/tools/synth_bracer/abilities/primary/anchor_form.dm
new file mode 100644
index 000000000000..a7e9c4982adb
--- /dev/null
+++ b/code/game/objects/items/tools/synth_bracer/abilities/primary/anchor_form.dm
@@ -0,0 +1,61 @@
+/datum/action/human_action/synth_bracer/anchor_form
+ name = "Anchor Form"
+ action_icon_state = "anchor"
+ cooldown = 15 SECONDS
+ charge_cost = SIMI_IMMOBILE_COST
+
+ handles_charge_cost = TRUE
+ handles_cooldown = TRUE
+ category = SIMI_PRIMARY_ACTION
+ ability_tag = SIMI_ABILITY_ANCHOR
+
+
+/datum/action/human_action/synth_bracer/anchor_form/can_use_action()
+ if(!issynth(synth))
+ to_chat(synth, SPAN_WARNING("You have no idea how to use this!"))
+ if(synth.is_mob_incapacitated() || synth.dazed)
+ to_chat(synth, SPAN_WARNING("You cannot use this action while incapacitated!"))
+ return FALSE
+ if((synth_bracer.battery_charge < charge_cost) && (synth_bracer.active_ability != ability_tag))
+ to_chat(synth, SPAN_WARNING("You don't have enough charge to to do this! Charge: [synth_bracer.battery_charge]/[synth_bracer.battery_charge_max] you need [SPAN_RED(charge_cost)]."))
+ return FALSE
+ if(!action_cooldown_check())
+ return FALSE
+ if((synth_bracer.active_ability != ability_tag) && (synth_bracer.active_ability != SIMI_ACTIVE_NONE))
+ to_chat(synth, SPAN_WARNING("You cannot use this action while another primary ability is active."))
+ return FALSE
+ return TRUE
+
+/datum/action/human_action/synth_bracer/anchor_form/form_call()
+ switch(synth_bracer.active_ability)
+ if(SIMI_ACTIVE_NONE)
+ synth_bracer.enable_anchor(charge_cost)
+ if(SIMI_ABILITY_ANCHOR)
+ synth_bracer.disable_anchor()
+ else
+ to_chat(synth, SPAN_WARNING("You cannot use this action while another primary ability is active."))
+ return FALSE
+
+ if(COOLDOWN_FINISHED(synth_bracer, sound_cooldown))
+ playsound(synth_bracer, 'sound/mecha/mechmove04.ogg', 25, TRUE)
+ COOLDOWN_START(synth_bracer, sound_cooldown, 5 SECONDS)
+ return TRUE
+
+/obj/item/clothing/gloves/synth/proc/enable_anchor(charge_cost)
+ set_active(SIMI_PRIMARY_ACTION, SIMI_ABILITY_ANCHOR)
+ drain_charge(wearer, charge_cost)
+ wearer.status_flags &= ~CANPUSH
+ wearer.anchored = TRUE
+ ADD_TRAIT(wearer, TRAIT_IMMOBILIZED, TRAIT_SOURCE_EQUIPMENT(WEAR_HANDS))
+ to_chat(wearer, SPAN_DANGER("[name] beeps, \"You are anchored in place and cannot be moved.\""))
+ wearer.add_filter("synth_immobile_form", priority = 1, params = list("type" = "outline", "color" = "#2B719E", "size" = 1))
+
+/obj/item/clothing/gloves/synth/proc/disable_anchor()
+ if(!(active_ability == SIMI_ABILITY_ANCHOR))
+ return FALSE
+ wearer.status_flags |= CANPUSH
+ wearer.anchored = FALSE
+ REMOVE_TRAIT(wearer, TRAIT_IMMOBILIZED, TRAIT_SOURCE_EQUIPMENT(WEAR_HANDS))
+ to_chat(wearer, SPAN_DANGER("[name] beeps, \"You can now move again.\""))
+ set_inactive(SIMI_PRIMARY_ACTION)
+ wearer.remove_filter("synth_immobile_form")
diff --git a/code/game/objects/items/tools/synth_bracer/abilities/primary/protect_form.dm b/code/game/objects/items/tools/synth_bracer/abilities/primary/protect_form.dm
new file mode 100644
index 000000000000..4246b780a73b
--- /dev/null
+++ b/code/game/objects/items/tools/synth_bracer/abilities/primary/protect_form.dm
@@ -0,0 +1,56 @@
+/datum/action/human_action/synth_bracer/protective_form
+ name = "Protective Form"
+ action_icon_state = "protect"
+ cooldown = 15 SECONDS
+ charge_cost = SIMI_PROTECTIVE_COST
+
+ handles_charge_cost = TRUE
+ handles_cooldown = TRUE
+ category = SIMI_PRIMARY_ACTION
+ ability_tag = SIMI_ABILITY_PROTECT
+
+/datum/action/human_action/synth_bracer/protective_form/form_call()
+ if((!issynth(synth) && !human_adaptable) || synth_bracer.active_ability != SIMI_ACTIVE_NONE)
+ return
+
+ if(synth_bracer.battery_charge < SIMI_PROTECTIVE_COST)
+ to_chat(synth, SPAN_DANGER("There is a lack of charge for that action. Charge: [synth_bracer.battery_charge]/[SIMI_PROTECTIVE_COST]"))
+ return
+ synth_bracer.enable_shield(charge_cost)
+
+
+/obj/item/clothing/gloves/synth/proc/enable_shield(charge_cost)
+ flags_item |= NODROP
+ flags_inventory |= CANTSTRIP
+ LAZYSET(wearer.brute_mod_override, src, 0.2)
+ LAZYSET(wearer.burn_mod_override, src, 0.2)
+ saved_melee_allowed = wearer.melee_allowed
+ saved_gun_allowed = wearer.allow_gun_usage
+ saved_throw_allowed = wearer.throw_allowed
+ wearer.melee_allowed = FALSE
+ wearer.allow_gun_usage = FALSE
+ wearer.throw_allowed = FALSE
+ to_chat(wearer, SPAN_DANGER("[name] beeps, \"You are now protected, but unable to attack.\""))
+ drain_charge(wearer, charge_cost)
+ playsound(loc, 'sound/mecha/mechmove04.ogg', 25, TRUE)
+ to_chat(wearer, SPAN_INFO("The current charge reads [battery_charge]/[SMARTPACK_MAX_POWER_STORED]"))
+ set_active(SIMI_PRIMARY_ACTION, SIMI_ABILITY_PROTECT)
+
+ wearer.add_filter("synth_protective_form", priority = 1, params = list("type" = "outline", "color" = "#369E2B", "size" = 1))
+
+ addtimer(CALLBACK(src, PROC_REF(disable_shield), wearer), 120)
+
+/obj/item/clothing/gloves/synth/proc/disable_shield(charge_cost)
+ if(!(active_ability == SIMI_ABILITY_PROTECT))
+ return FALSE
+ flags_item &= ~NODROP
+ flags_inventory &= ~CANTSTRIP
+ wearer.melee_allowed = saved_melee_allowed
+ wearer.throw_allowed = saved_throw_allowed
+ wearer.allow_gun_usage = saved_gun_allowed
+ LAZYREMOVE(wearer.brute_mod_override, src)
+ LAZYREMOVE(wearer.burn_mod_override, src)
+ to_chat(wearer, SPAN_DANGER("[name] beeps, \"The protection wears off.\""))
+ playsound(loc, 'sound/mecha/mechmove04.ogg', 25, TRUE)
+ set_inactive(SIMI_PRIMARY_ACTION)
+ wearer.remove_filter("synth_protective_form")
diff --git a/code/game/objects/items/tools/synth_bracer/abilities/primary/repair_form.dm b/code/game/objects/items/tools/synth_bracer/abilities/primary/repair_form.dm
new file mode 100644
index 000000000000..ba64e27fa279
--- /dev/null
+++ b/code/game/objects/items/tools/synth_bracer/abilities/primary/repair_form.dm
@@ -0,0 +1,32 @@
+/datum/action/human_action/synth_bracer/repair_form
+ name = "Repair Form"
+ action_icon_state = "repair"
+ cooldown = 15 SECONDS
+ charge_cost = SIMI_REPAIR_COST
+
+ handles_charge_cost = TRUE
+ handles_cooldown = TRUE
+ category = SIMI_PRIMARY_ACTION
+ ability_tag = SIMI_ABILITY_REPAIR
+
+/datum/action/human_action/synth_bracer/repair_form/form_call()
+ if(synth.getBruteLoss() <= 0 && synth.getFireLoss() <= 0)
+ to_chat(synth, SPAN_WARNING("[synth_bracer.name] beeps, \"No noticeable damage. Procedure cancelled.\""))
+ return
+
+ set_active(category, SIMI_ABILITY_REPAIR)
+ synth.visible_message(SPAN_WARNING("[synth_bracer.name] beeps, \"Engaging the repairing process.\""), SPAN_WARNING("[synth_bracer.name] beeps, \"Beginning to carefully examine your sustained damage.\""))
+ playsound(synth.loc, 'sound/mecha/mechmove04.ogg', 25, TRUE)
+ if(!do_after(synth, 5 SECONDS, INTERRUPT_ALL, BUSY_ICON_FRIENDLY))
+ to_chat(synth, SPAN_DANGER("[synth_bracer.name] beeps, \"Repair process was cancelled.\""))
+ set_inactive(category)
+ return
+
+ enter_cooldown()
+ synth_bracer.drain_charge(synth, charge_cost)
+
+ playsound(synth.loc, 'sound/items/Welder2.ogg', 25, TRUE)
+ synth.heal_overall_damage(25, 25, TRUE)
+ synth.pain.recalculate_pain()
+ synth.visible_message(SPAN_NOTICE("[synth_bracer.name] beeps, \"Completed the repairing process.\""))
+ set_inactive(category)
diff --git a/code/game/objects/items/tools/synth_bracer/abilities/utility/motion_detector.dm b/code/game/objects/items/tools/synth_bracer/abilities/utility/motion_detector.dm
new file mode 100644
index 000000000000..dff3e2cc3203
--- /dev/null
+++ b/code/game/objects/items/tools/synth_bracer/abilities/utility/motion_detector.dm
@@ -0,0 +1,84 @@
+/obj/item/clothing/gloves/synth
+ var/obj/item/device/motiondetector/integrated/motion_detector
+ var/motion_detector_active = FALSE
+ var/motion_detector_recycle = 120
+ var/motion_detector_cooldown = 2
+ var/motion_detector_cost = 2
+
+/obj/item/clothing/gloves/synth/Initialize(mapload, ...)
+ . = ..()
+ motion_detector = new(src)
+ motion_detector.iff_signal = faction
+
+/obj/item/clothing/gloves/synth/process()
+ if(!ishuman(loc))
+ STOP_PROCESSING(SSobj, src)
+ return
+ if(!motion_detector_active)
+ STOP_PROCESSING(SSobj, src)
+ return
+ if(battery_charge <= 1)
+ motion_detector_active = FALSE
+ STOP_PROCESSING(SSobj, src)
+ return
+ if(motion_detector_active)
+ motion_detector_recycle--
+ if(!motion_detector_recycle)
+ motion_detector_recycle = initial(motion_detector_recycle)
+ motion_detector.refresh_blip_pool()
+
+ motion_detector_cooldown--
+ if(motion_detector_cooldown)
+ return
+ motion_detector_cooldown = initial(motion_detector_cooldown)
+ motion_detector.scan()
+ drain_charge(loc, 2, FALSE)
+
+/obj/item/clothing/gloves/synth/dropped(mob/user)
+ . = ..()
+ if(motion_detector && motion_detector_active)
+ toggle_motion_detector(user)
+
+/obj/item/clothing/gloves/synth/Destroy()
+ QDEL_NULL(motion_detector)
+ . = ..()
+
+/obj/item/clothing/gloves/synth/proc/toggle_motion_detector(mob/user)
+ if(!motion_detector)
+ to_chat(user, SPAN_WARNING("No motion detector located!"))
+ return FALSE
+ to_chat(user, SPAN_NOTICE("You [motion_detector_active? "disable" : "enable"] \the [src]'s motion detector."))
+ if(COOLDOWN_FINISHED(src, sound_cooldown))
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 35, TRUE)
+ COOLDOWN_START(src, sound_cooldown, 5 SECONDS)
+ motion_detector_active = !motion_detector_active
+ var/datum/action/human_action/synth_bracer/motion_detector/TMD = locate(/datum/action/human_action/synth_bracer/motion_detector) in actions_list_actions
+ TMD.update_icon()
+ update_icon()
+
+ if(!motion_detector_active)
+ STOP_PROCESSING(SSobj, src)
+ else
+ START_PROCESSING(SSobj, src)
+ return TRUE
+
+/datum/action/human_action/synth_bracer/motion_detector
+ name = "Toggle Motion Detector"
+ action_icon_state = "motion_detector"
+ handles_charge_cost = TRUE
+ handles_cooldown = TRUE
+ charge_cost = 2
+ human_adaptable = TRUE
+
+/datum/action/human_action/synth_bracer/motion_detector/action_activate()
+ ..()
+ synth_bracer.toggle_motion_detector(synth)
+
+/datum/action/human_action/synth_bracer/motion_detector/proc/update_icon()
+ if(!synth_bracer)
+ return
+
+ if(synth_bracer.motion_detector_active)
+ button.icon_state = "template_on"
+ else
+ button.icon_state = "template"
diff --git a/code/game/objects/items/tools/synth_bracer/abilities/utility/rescue_hook.dm b/code/game/objects/items/tools/synth_bracer/abilities/utility/rescue_hook.dm
new file mode 100644
index 000000000000..9e61379e2977
--- /dev/null
+++ b/code/game/objects/items/tools/synth_bracer/abilities/utility/rescue_hook.dm
@@ -0,0 +1,114 @@
+/datum/action/human_action/activable/synth_bracer/rescue_hook
+ name = "Rescue Hook"
+ action_icon_state = "hook"
+ cooldown = 5 SECONDS
+ charge_cost = 65
+
+ handles_cooldown = TRUE
+ handles_charge_cost = TRUE
+
+ // Config
+ var/max_distance = 3
+ var/windup = 10
+ human_adaptable = TRUE
+ ability_tag = SIMI_SECONDARY_HOOK
+
+/datum/action/human_action/activable/synth_bracer/rescue_hook/use_ability(atom/atom_target)
+ . = ..()
+ if(!.)
+ return FALSE
+
+ if(!atom_target || atom_target.layer >= FLY_LAYER || !isturf(synth.loc))
+ return FALSE
+
+ if(!action_cooldown_check() || synth.action_busy)
+ return FALSE
+
+ set_active(category, ability_tag)
+ // Build our turflist
+ var/list/turf/turflist = list()
+ var/list/telegraph_atom_list = list()
+ var/facing = get_dir(synth, atom_target)
+ var/turf/T = synth.loc
+ var/turf/temp = synth.loc
+ for(var/x in 0 to max_distance)
+ temp = get_step(T, facing)
+ if(facing in GLOB.diagonals) // check if it goes through corners
+ var/reverse_face = GLOB.reverse_dir[facing]
+ var/turf/back_left = get_step(temp, turn(reverse_face, 45))
+ var/turf/back_right = get_step(temp, turn(reverse_face, -45))
+ if((!back_left || back_left.density) && (!back_right || back_right.density))
+ break
+ if(!temp || temp.density || temp.opacity)
+ break
+
+ var/blocked = FALSE
+ for(var/obj/structure/S in temp)
+ if(S.opacity || ((istype(S, /obj/structure/barricade) || istype(S, /obj/structure/machinery/door)) && S.density))
+ blocked = TRUE
+ break
+ if(blocked)
+ break
+
+ T = temp
+
+ if (T in turflist)
+ break
+
+ turflist += T
+ facing = get_dir(T, atom_target)
+ telegraph_atom_list += new /obj/effect/simi_hook(T, windup)
+
+ if(!length(turflist))
+ to_chat(synth, SPAN_WARNING("You don't have any room to launch your hook!"))
+ set_inactive(category)
+ return FALSE
+
+ synth.visible_message(SPAN_DANGER("[synth] prepares to launch a rescue hook at [atom_target]!"), SPAN_DANGER("You prepare to launch a rescue hook at [atom_target]!"))
+
+ var/throw_target_turf = get_step(synth.loc, facing)
+ var/pre_frozen = FALSE
+ if(HAS_TRAIT(synth, TRAIT_IMMOBILIZED))
+ pre_frozen = TRUE
+ else
+ ADD_TRAIT(synth, TRAIT_IMMOBILIZED, TRAIT_SOURCE_EQUIPMENT(WEAR_HANDS))
+ if(!do_after(synth, windup, INTERRUPT_NO_NEEDHAND, BUSY_ICON_HOSTILE, null, null, FALSE, 1, FALSE, 1))
+ to_chat(synth, SPAN_WARNING("You cancel your launch."))
+
+ for (var/obj/effect/xenomorph/xeno_telegraph/XT in telegraph_atom_list)
+ telegraph_atom_list -= XT
+ qdel(XT)
+ if(!pre_frozen)
+ REMOVE_TRAIT(synth, TRAIT_IMMOBILIZED, TRAIT_SOURCE_EQUIPMENT(WEAR_HANDS))
+ set_inactive(category)
+
+ return FALSE
+
+ enter_cooldown()
+ synth_bracer.drain_charge(synth, charge_cost)
+
+ if(!pre_frozen)
+ REMOVE_TRAIT(synth, TRAIT_IMMOBILIZED, TRAIT_SOURCE_EQUIPMENT(WEAR_HANDS))
+
+ playsound(get_turf(synth), 'sound/items/rappel.ogg', 75, FALSE)
+
+ var/mob/living/carbon/human/marine_target
+ for(var/turf/target_turf in turflist)
+ for(var/mob/living/carbon/human/marine in target_turf)
+ marine_target = marine
+ continue
+
+ if(marine_target)
+ to_chat(marine_target, SPAN_DANGER("You are pulled towards [synth]!"))
+ marine_target.KnockDown(0.2)
+ shake_camera(marine_target, 10, 1)
+ marine_target.throw_atom(throw_target_turf, get_dist(throw_target_turf, marine_target)-1, SPEED_VERY_FAST)
+ set_inactive(category)
+
+/obj/effect/simi_hook
+ icon = 'icons/obj/items/synth/bracer.dmi'
+ icon_state = "holo_hook_telegraph_anim"
+
+/obj/effect/simi_hook/Initialize(mapload, ttl = 1 SECONDS)
+ . = ..()
+ QDEL_IN(src, ttl)
diff --git a/code/game/objects/items/tools/synth_bracer/bracer_subtypes.dm b/code/game/objects/items/tools/synth_bracer/bracer_subtypes.dm
new file mode 100644
index 000000000000..4bc17ae898bd
--- /dev/null
+++ b/code/game/objects/items/tools/synth_bracer/bracer_subtypes.dm
@@ -0,0 +1,52 @@
+/obj/item/clothing/gloves/synth/wy
+ name = "PK-130C SIMI wrist-mounted computer"
+ desc = "Developed by a joint effort between Weyland-Yutani CIART and the USCM R&D Division, the SIMI portable computer is the ultimate solution for situational awareness, personnel monitoring and communication. This one has a corporate-white finish."
+
+ icon_state = "bracer_white"
+ base_item_slot_state = "bracer_white"
+ item_state_slots = list(
+ WEAR_HANDS = "bracer_white"
+ )
+
+ bracer_color = SIMI_COLOR_WHITE
+ faction = FACTION_WY
+
+/obj/item/clothing/gloves/synth/wy/pmc
+ faction = FACTION_PMC
+
+/obj/item/clothing/gloves/synth/wy/pmc/preset
+ faction = FACTION_PMC
+ actions_list_added = list(
+ /datum/action/human_action/synth_bracer/repair_form,
+ /datum/action/human_action/synth_bracer/motion_detector,
+ )
+
+/obj/item/clothing/gloves/synth/wy/pmc/preset/Initialize()
+ . = ..()
+ underglove = new /obj/item/clothing/gloves/marine/veteran/pmc(src)
+
+ var/obj/item/device/simi_chip/motion_detector/new_md = new
+ var/obj/item/device/simi_chip/repair/new_repair = new
+ new_md.forceMove(src)
+ ability_chips += new_md
+ new_repair.forceMove(src)
+ ability_chips += new_repair
+
+/obj/item/clothing/gloves/synth/testing
+ name = "XPK-140 SIMI wrist-mounted computer"
+ desc = "Developed by a joint effort between Weyland-Yutani CIART and the USCM R&D Division, the SIMI portable computer is the ultimate solution for situational awareness, personnel monitoring and communication. This one is highly experimental and seems to be overclocked."
+ ability_chips_max = 0
+
+ actions_list_inherent = list(
+ /datum/action/human_action/synth_bracer/crew_monitor,
+ /datum/action/human_action/synth_bracer/deploy_binoculars,
+ /datum/action/human_action/synth_bracer/tactical_map,
+ )
+ //pre-populated list for testing purposes.
+ actions_list_added = list(
+ /datum/action/human_action/synth_bracer/repair_form,
+ /datum/action/human_action/synth_bracer/protective_form,
+ /datum/action/human_action/synth_bracer/anchor_form,
+ /datum/action/human_action/activable/synth_bracer/rescue_hook,
+ /datum/action/human_action/synth_bracer/motion_detector,
+ )
diff --git a/code/game/objects/items/tools/synth_bracer/synth_bracer.dm b/code/game/objects/items/tools/synth_bracer/synth_bracer.dm
new file mode 100644
index 000000000000..f618d55478e4
--- /dev/null
+++ b/code/game/objects/items/tools/synth_bracer/synth_bracer.dm
@@ -0,0 +1,469 @@
+/obj/item/clothing/gloves/synth
+ name = "PK-130 SIMI wrist-mounted computer"
+ desc = "Developed by a joint effort between Weyland-Yutani CIART and the USCM R&D Division, the SIMI portable computer is the ultimate solution for situational awareness, personnel monitoring and communication."
+
+ icon = 'icons/obj/items/synth/bracer.dmi'
+ icon_state = "bracer_default"
+ item_icons = list(
+ WEAR_HANDS = 'icons/mob/humans/onmob/synth/bracer.dmi'
+ )
+
+ var/base_item_slot_state = "bracer_default"
+ item_state_slots = list(
+ WEAR_HANDS = "bracer_default"
+ )
+
+ siemens_coefficient = 0
+ permeability_coefficient = 0.05
+ flags_cold_protection = BODY_FLAG_HANDS
+ flags_heat_protection = BODY_FLAG_HANDS
+ flags_armor_protection = BODY_FLAG_HANDS
+ flags_inventory = CANTSTRIP
+ min_cold_protection_temperature = GLOVES_MIN_COLD_PROT
+ max_heat_protection_temperature = GLOVES_MAX_HEAT_PROT
+
+ armor_melee = CLOTHING_ARMOR_MEDIUM
+ armor_bullet = CLOTHING_ARMOR_MEDIUM
+ armor_laser = CLOTHING_ARMOR_MEDIUM
+ armor_energy = CLOTHING_ARMOR_MEDIUM
+ armor_bomb = CLOTHING_ARMOR_MEDIUMHIGH
+ armor_bio = CLOTHING_ARMOR_MEDIUM
+ armor_rad = CLOTHING_ARMOR_MEDIUM
+ armor_internaldamage = CLOTHING_ARMOR_MEDIUM
+
+ var/battery_charge = SMARTPACK_MAX_POWER_STORED
+ var/battery_charge_max = SMARTPACK_MAX_POWER_STORED
+ var/bracer_charging = FALSE
+
+ var/list/ability_chips = list()
+ var/ability_chips_max = 2
+
+ var/list/actions_list_inherent = list(
+ /datum/action/human_action/synth_bracer/crew_monitor,
+ /datum/action/human_action/synth_bracer/deploy_binoculars,
+ /datum/action/human_action/synth_bracer/tactical_map,
+ )
+ var/list/actions_list_added = list()
+
+ var/list/datum/action/human_action/synth_bracer/actions_list_actions = list()
+ var/active_ability = SIMI_ACTIVE_NONE
+ var/active_utility = SIMI_ACTIVE_NONE
+
+ /// Faction used by Internal Phone & Crew Monitor
+ var/faction = FACTION_MARINE
+
+ /// If the bracer is adapted for human use. (No using repair mode etc.)
+ var/human_adapted = FALSE
+
+ /// Internal Phone
+ var/obj/structure/transmitter/internal/internal_transmitter
+
+ /// Pair of gloves worn underneath the computer.
+ var/obj/item/clothing/gloves/underglove
+ /// Base color of the bracer. (DEFAULT OR WHITE)
+ var/bracer_color = SIMI_COLOR_DEFAULT
+
+ // Capability states used in FORITIFY mode.
+ var/saved_melee_allowed = TRUE
+ var/saved_throw_allowed = TRUE
+ var/saved_gun_allowed = FALSE
+
+ var/mob/living/carbon/human/wearer
+
+ /// Cooldown on abilities that play sounds (and don't internally handle it)
+ COOLDOWN_DECLARE(sound_cooldown)
+
+/obj/item/clothing/gloves/synth/Initialize(mapload, ...)
+ . = ..()
+ update_actions()
+
+ internal_transmitter = new(src)
+ internal_transmitter.relay_obj = src
+ internal_transmitter.phone_category = "Synth"
+ internal_transmitter.enabled = FALSE
+ internal_transmitter.range = 2
+ internal_transmitter.networks_receive = list(faction)
+ internal_transmitter.networks_transmit = list(faction)
+ RegisterSignal(internal_transmitter, COMSIG_TRANSMITTER_UPDATE_ICON, PROC_REF(check_for_ringing))
+
+/obj/item/clothing/gloves/synth/Destroy()
+ . = ..()
+ QDEL_NULL_LIST(actions_list_actions)
+ QDEL_NULL(internal_transmitter)
+ QDEL_NULL(underglove)
+
+/obj/item/clothing/gloves/synth/examine(mob/user)
+ ..()
+ to_chat(user, SPAN_INFO("The current charge reads [battery_charge]/[battery_charge_max]."))
+ if(underglove)
+ to_chat(user, SPAN_INFO("The wrist-strap is attached to [underglove]."))
+ else
+ to_chat(user, SPAN_NOTICE("You see a way to attach a pair of gloves to the wrist-strap."))
+
+/obj/item/clothing/gloves/synth/equipped(mob/user, slot)
+ . = ..()
+ if(slot == WEAR_HANDS)
+ update_actions(SIMI_ACTIONS_ADD, user)
+ flick("bracer_[bracer_color]_startup", src)
+
+ if(ishuman(user))
+ wearer = user
+ if(wearer.comm_title)
+ internal_transmitter.phone_id = "[wearer.comm_title] [wearer]"
+ else if(wearer.job)
+ internal_transmitter.phone_id = "[wearer.job] [wearer]"
+ else
+ internal_transmitter.phone_id = "[wearer]"
+ if(wearer.assigned_squad)
+ internal_transmitter.phone_id += " ([wearer.assigned_squad.name])"
+ else
+ internal_transmitter.phone_id = "[user]"
+ internal_transmitter.enabled = TRUE
+
+ update_icon()
+
+/obj/item/clothing/gloves/synth/dropped(mob/user)
+ disable_anchor()
+ disable_shield()
+
+ update_actions(SIMI_ACTIONS_REMOVE, user)
+
+ if(bracer_charging)
+ stop_charging(user)
+ update_icon()
+
+ if(internal_transmitter)
+ internal_transmitter.phone_id = "[src]"
+ internal_transmitter.enabled = FALSE
+
+ wearer = null
+ return ..()
+
+/obj/item/clothing/gloves/synth/MouseDrop(obj/over_object as obj)
+ if(CAN_PICKUP(usr, src))
+ if(!istype(over_object, /atom/movable/screen))
+ return ..()
+
+ if(!usr.is_mob_restrained() && !usr.stat)
+ switch(over_object.name)
+ if("r_hand")
+ if(usr.drop_inv_item_on_ground(src))
+ usr.put_in_r_hand(src)
+ if("l_hand")
+ if(usr.drop_inv_item_on_ground(src))
+ usr.put_in_l_hand(src)
+ add_fingerprint(usr)
+
+/obj/item/clothing/gloves/synth/attackby(obj/item/attacker, mob/living/carbon/human/user)
+ if((istype(attacker, /obj/item/clothing/gloves)) && !(attacker.flags_item & ITEM_PREDATOR))
+ if(underglove)
+ to_chat(user, SPAN_WARNING("[src] is already attached to [underglove], remove them first."))
+ return
+ underglove = attacker
+ user.drop_inv_item_to_loc(attacker, src)
+ to_chat(user, SPAN_NOTICE("You attach the [attacker] to the bracer's wrist-strap."))
+ user.update_inv_gloves()
+ if(internal_transmitter.attached_to == attacker)
+ internal_transmitter.attackby(attacker, user)
+ return
+
+ if(istype(attacker, /obj/item/device/simi_chip))
+ var/obj/item/device/simi_chip/new_chip = attacker
+ var/chips_num = 0
+ for(var/obj/item/device/simi_chip/chip in ability_chips)
+ if(chip.chip_action == new_chip.chip_action)
+ to_chat(user, SPAN_WARNING("[src] already has this circuit chip!"))
+ return
+ if(!chip.secret)
+ chips_num++
+ if(chips_num >= ability_chips_max)
+ to_chat(user, SPAN_WARNING("[src] can't hold another circuit chip!"))
+ return
+ if(user.drop_held_item())
+ new_chip.forceMove(src)
+ ability_chips += new_chip
+ to_chat(user, SPAN_NOTICE("You slot [new_chip] into [src]!"))
+ playsound(src, 'sound/machines/terminal_processing.ogg', 15, TRUE)
+ if(user.gloves && (user.gloves == src))
+ update_actions(SIMI_ACTIONS_RELOAD, user)
+ else
+ update_actions(SIMI_ACTIONS_RELOAD)
+ return
+
+ if(HAS_TRAIT(attacker, TRAIT_TOOL_SCREWDRIVER))
+ //Remove ability chip - give option or remove all?
+ var/turf/T = get_turf(user)
+ if(!T)
+ to_chat(user, "You cannot do that here.")
+ return
+
+ var/removed_chips = FALSE
+ for (var/obj/item/device/simi_chip/chip in ability_chips)
+ if(chip.secret)
+ continue
+ chip.forceMove(T)
+ ability_chips -= chip
+ removed_chips = TRUE
+ if(removed_chips)
+ if(user.gloves && (user.gloves == src))
+ update_actions(SIMI_ACTIONS_RELOAD, user)
+ else
+ update_actions(SIMI_ACTIONS_RELOAD)
+ to_chat(user, SPAN_NOTICE("You pop out the circuit chips from [src]!"))
+ else
+ to_chat(user, SPAN_NOTICE("There are no removable circuit chips in [src]!"))
+ return
+ return ..()
+
+/obj/item/clothing/gloves/synth/attack_hand(mob/living/carbon/human/user)
+ if(istype(user) && user.gloves == src)
+ internal_transmitter.attack_hand(user)
+ return
+ return ..()
+
+/obj/item/clothing/gloves/synth/forceMove(atom/dest)
+ . = ..()
+ if(isturf(dest))
+ internal_transmitter.set_tether_holder(src)
+ else
+ internal_transmitter.set_tether_holder(loc)
+
+/obj/item/clothing/gloves/synth/proc/set_active(category = SIMI_SECONDARY_ACTION, set_ability = SIMI_ACTIVE_NONE)
+ switch(category)
+ if(SIMI_PRIMARY_ACTION)
+ active_ability = set_ability
+ if(SIMI_SECONDARY_ACTION)
+ active_utility = set_ability
+ if((active_ability == SIMI_ACTIVE_NONE) && (active_utility == SIMI_ACTIVE_NONE))
+ flags_item &= ~NODROP
+ else
+ flags_item |= NODROP
+ update_icon()
+
+/obj/item/clothing/gloves/synth/proc/set_inactive(category = SIMI_SECONDARY_ACTION)
+ set_active(category, SIMI_ACTIVE_NONE)
+
+//#############################
+//###### ICON HANDLING ########
+//#############################
+/obj/item/clothing/gloves/synth/update_icon()
+ var/mob/living/carbon/human/wearer = loc
+ if(!istype(wearer) || wearer.gloves != src)
+ overlays.Cut()
+ icon_state = "bracer_[bracer_color]"
+ return
+
+ icon_state = "bracer_[bracer_color]_blank"
+
+ update_overlays()
+
+/obj/item/clothing/gloves/synth/proc/get_bracer_status()
+ if(battery_charge <= 0)
+ internal_transmitter.enabled = FALSE
+ return SIMI_STATUS_NOPOWER
+ if(battery_charge <= battery_charge_max * 0.1)
+ return SIMI_STATUS_LOWPOWER
+ var/mob/living/carbon/human/wearer = loc
+ if(!issynth(wearer) && !human_adapted)
+ internal_transmitter.enabled = FALSE
+ return SIMI_STATUS_NOACCESS
+ internal_transmitter.enabled = TRUE
+ return SIMI_STATUS_IDLE
+
+/obj/item/clothing/gloves/synth/proc/update_overlays()
+ overlays.Cut()
+
+ var/image/idle_image = image(icon, src, SIMI_STATUS_IDLE)
+ idle_image.appearance_flags = RESET_COLOR|KEEP_APART
+ var/current_status = get_bracer_status()
+ var/image/status_image
+ if(current_status != SIMI_STATUS_IDLE)
+ status_image = image(icon, src, current_status)
+ status_image.appearance_flags = RESET_COLOR|KEEP_APART
+
+ var/phone_status
+ if(internal_transmitter && internal_transmitter.attached_to)
+ if(internal_transmitter.do_not_disturb >= PHONE_DND_ON)
+ phone_status = "dnd"
+ else if(internal_transmitter.attached_to.loc != internal_transmitter)
+ phone_status = "listening"
+ else if(internal_transmitter.caller)
+ phone_status = "ringing"
+
+ var/image/phone_image = image(icon, src, "phone_[phone_status]")
+ phone_image.appearance_flags = RESET_COLOR|KEEP_APART
+
+ var/image/secondary_image = image(icon, src, "secondary_[active_utility]")
+ secondary_image.appearance_flags = RESET_COLOR|KEEP_APART
+
+ var/image/primary_image = image(icon, src, "primary_[active_ability]")
+ primary_image.appearance_flags = RESET_COLOR|KEEP_APART
+
+ if(motion_detector_active)
+ var/image/motion_image = image(icon, src, "motion_active")
+ motion_image.appearance_flags = RESET_COLOR|KEEP_APART
+ overlays += motion_image
+
+ overlays += idle_image
+ overlays += phone_image
+ overlays += secondary_image
+ overlays += primary_image
+ overlays += status_image
+
+
+/obj/item/clothing/gloves/synth/proc/check_for_ringing()
+ SIGNAL_HANDLER
+ update_overlays()
+
+/obj/item/clothing/gloves/synth/get_mob_overlay(mob/user_mob, slot)
+ var/image/overlay = ..()
+
+ if((slot != WEAR_HANDS) || !underglove)
+ return overlay
+
+ overlay = underglove.get_mob_overlay(user_mob, slot)
+
+ var/image/bracer_img = overlay_image('icons/mob/humans/onmob/synth/bracer.dmi', get_icon_state(user_mob, slot), null, RESET_COLOR|NO_CLIENT_COLOR)
+ overlay.overlays += bracer_img
+
+ return overlay
+
+/obj/item/clothing/gloves/synth/verb/swap_hands()
+ set name = "Swap Hands"
+ set src in usr
+
+ if(base_item_slot_state == "bracer_[bracer_color]")
+ base_item_slot_state = "bracer_[bracer_color]_r"
+ else
+ base_item_slot_state = "bracer_[bracer_color]"
+ item_state_slots[WEAR_HANDS] = base_item_slot_state
+
+ to_chat(usr, SPAN_NOTICE("You shift \the [src] over to your [base_item_slot_state == "bracer_[bracer_color]" ? "left arm" : "right arm"]."))
+ usr.update_inv_gloves()
+
+/obj/item/clothing/gloves/synth/verb/remove_gloves()
+ set name = "Remove Gloves"
+ set src in usr
+
+ if(!underglove)
+ return FALSE
+
+ to_chat(usr, SPAN_NOTICE("You remove [underglove] from the wrist-strap."))
+ underglove.forceMove(get_turf(usr))
+ underglove = null
+
+ usr.update_inv_gloves()
+
+//#############################
+//######## CHARGING ###########
+//#############################
+/obj/item/clothing/gloves/synth/proc/handle_apc_charge(mob/living/carbon/human/user, obj/structure/machinery/power/apc/apc)
+ if(!istype(user))
+ return FALSE
+
+ if(!(user.species.flags & IS_SYNTHETIC) || user.a_intent != INTENT_GRAB)
+ return FALSE
+
+ if(user.action_busy)
+ return FALSE
+
+ INVOKE_ASYNC(src, PROC_REF(complete_apc_charge), user, apc)
+
+/obj/item/clothing/gloves/synth/proc/complete_apc_charge(mob/living/carbon/human/user, obj/structure/machinery/power/apc/apc)
+ start_charging(user)
+
+ if(!do_after(user, 6 SECONDS, INTERRUPT_ALL, BUSY_ICON_GENERIC))
+ stop_charging(user)
+ return
+ if(!user.Adjacent(apc) || (user.gloves != src))
+ stop_charging(user)
+ return
+
+ playsound(apc.loc, 'sound/effects/sparks2.ogg', 25, 1)
+
+ if(apc.stat & BROKEN)
+ var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
+ s.set_up(3, 1, apc)
+ s.start()
+ to_chat(user, SPAN_DANGER("The APC's power currents surge eratically, damaging your chassis!"))
+ user.apply_damage(10, 0, BURN)
+ else if(apc.cell?.charge > 0)
+ if(battery_charge < battery_charge_max)
+ var/charge_to_use = min(apc.cell.charge, battery_charge_max - battery_charge)
+ if(!(apc.cell.use(charge_to_use)))
+ stop_charging(user)
+ return
+ battery_charge += charge_to_use
+ to_chat(user, SPAN_NOTICE("You slot your fingers into the APC interface and siphon off some of the stored charge. \The [src] now has [battery_charge]/[battery_charge_max]."))
+ apc.charging = 1 //APC_CHARGING
+ else
+ to_chat(user, SPAN_WARNING("\The [src] is already fully charged."))
+ else
+ to_chat(user, SPAN_WARNING("There is no charge to draw from that APC."))
+ stop_charging(user)
+
+/obj/item/clothing/gloves/synth/proc/start_charging(mob/user)
+ bracer_charging = TRUE
+ item_state_slots[WEAR_HANDS] += "_charging"
+
+ var/image/charge_image = image(icon, src, SIMI_STATUS_CHARGING)
+ charge_image.appearance_flags = RESET_COLOR|KEEP_APART
+ overlays += charge_image
+
+ user.update_inv_gloves()
+
+/obj/item/clothing/gloves/synth/proc/stop_charging(mob/user)
+ bracer_charging = FALSE
+ item_state_slots[WEAR_HANDS] = base_item_slot_state
+ update_icon()
+ user.update_inv_gloves()
+
+/obj/item/clothing/gloves/synth/proc/drain_charge(mob/user, cost, report_charge = TRUE)
+ battery_charge = max(0, battery_charge -= cost)
+ if(report_charge)
+ to_chat(user, SPAN_WARNING("\The [src]'s charge now reads: [battery_charge]/[battery_charge_max]."))
+ update_icon()
+
+//#############################
+//##### ACTION HANDLING #######
+//#############################
+/obj/item/clothing/gloves/synth/proc/update_actions(mode = SIMI_ACTIONS_LOAD, mob/user)
+ if((!user) && ((mode != SIMI_ACTIONS_LOAD) && (mode != SIMI_ACTIONS_RELOAD)))
+ return FALSE
+
+ switch(mode)
+ if(SIMI_ACTIONS_LOAD)
+ for(var/action_type in actions_list_inherent)
+ actions_list_actions += new action_type
+ for(var/action_type in actions_list_added)
+ actions_list_actions += new action_type
+
+ if(SIMI_ACTIONS_RELOAD)
+ actions_list_added.Cut()
+ for(var/obj/item/device/simi_chip/chip in ability_chips)
+ actions_list_added += chip.chip_action
+ if(user)
+ for(var/datum/action/human_action/action as anything in actions_list_actions)
+ action.remove_from(user)
+ for(var/datum/action/human_action/action in actions_list_actions)
+ actions_list_actions -= action
+ qdel(action)
+ update_actions(SIMI_ACTIONS_LOAD)
+ if(user)
+ for(var/datum/action/human_action/action as anything in actions_list_actions)
+ action.give_to(user)
+
+ if(SIMI_ACTIONS_ADD)
+ for(var/datum/action/human_action/action as anything in actions_list_actions)
+ action.remove_from(user)
+ for(var/datum/action/human_action/action as anything in actions_list_actions)
+ action.give_to(user)
+
+ if(SIMI_ACTIONS_REMOVE)
+ for(var/datum/action/human_action/action as anything in actions_list_actions)
+ action.remove_from(user)
+ else
+ return FALSE
+ return TRUE
+
+
diff --git a/code/modules/gear_presets/pmc.dm b/code/modules/gear_presets/pmc.dm
index e280060cae34..2e1dac10588f 100644
--- a/code/modules/gear_presets/pmc.dm
+++ b/code/modules/gear_presets/pmc.dm
@@ -1898,10 +1898,10 @@ list("POUCHES (CHOOSE 2)", 0, null, null, null),
new_human.equip_to_slot_or_del(new /obj/item/clothing/glasses/night/experimental_mesons, WEAR_EYES)
new_human.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/pmc, WEAR_FACE)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/pmc, WEAR_HANDS)
+ new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/synth/wy/pmc/preset, WEAR_HANDS)
new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/veteran/pmc/knife, WEAR_FEET)
- new_human.equip_to_slot_or_del(new /obj/item/storage/backpack/marine/smartpack/white, WEAR_BACK)
+ new_human.equip_to_slot_or_del(new /obj/item/storage/backpack/lightpack, WEAR_BACK)
new_human.equip_to_slot_or_del(new /obj/item/roller, WEAR_IN_BACK)
new_human.equip_to_slot_or_del(new /obj/item/roller/surgical, WEAR_IN_BACK)
new_human.equip_to_slot_or_del(new /obj/item/tool/extinguisher/mini, WEAR_IN_BACK)
@@ -1925,9 +1925,10 @@ list("POUCHES (CHOOSE 2)", 0, null, null, null),
/datum/equipment_preset/pmc/synth/get_antag_clothing_equipment()
return list(
list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null),
+ list("PK-130 SIMI wrist-mounted computer", 0, /obj/item/clothing/gloves/synth/wy/pmc, MARINE_CAN_BUY_ATTACHMENT, VENDOR_ITEM_MANDATORY),
+ list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran/pmc, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY),
list("Boots", 0, /obj/item/clothing/shoes/veteran/pmc/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY),
list("Fatigues", 0, /obj/item/clothing/under/marine/veteran/pmc, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY),
- list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran/pmc, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY),
list("Headset", 0, /obj/item/device/radio/headset/distress/pmc/hvh, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY),
list("MRE", 0, /obj/item/storage/box/MRE, MARINE_CAN_BUY_MRE, VENDOR_ITEM_MANDATORY),
list("Armored Balaclava", 0, /obj/item/clothing/mask/gas/pmc, MARINE_CAN_BUY_MASK, VENDOR_ITEM_MANDATORY),
@@ -1945,11 +1946,6 @@ list("POUCHES (CHOOSE 2)", 0, null, null, null),
list("Drop Pouch", 0, /obj/item/clothing/accessory/storage/droppouch, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR),
list("BACKPACK (CHOOSE 1)", 0, null, null, null),
- list("Smartpack, Blue", 0, /obj/item/storage/backpack/marine/smartpack, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR),
- list("Smartpack, Green", 0, /obj/item/storage/backpack/marine/smartpack/green, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR),
- list("Smartpack, Tan", 0, /obj/item/storage/backpack/marine/smartpack/tan, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR),
- list("Smartpack, White", 0, /obj/item/storage/backpack/marine/smartpack/white, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR),
- list("Smartpack, Black", 0, /obj/item/storage/backpack/marine/smartpack/black, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR),
list("Logistics IMP Backpack", 0, /obj/item/storage/backpack/marine/satchel/big, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR),
list("BELT (CHOOSE 1)", 0, null, null, null),
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 8ff67fa4b91c..f237329dcc7b 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -819,38 +819,46 @@ GLOBAL_LIST_INIT(apc_wire_descriptions, list(
if(grabber.a_intent == INTENT_GRAB)
//Synthpack recharge
- if((grabber.species.flags & IS_SYNTHETIC) && istype(grabber.back, /obj/item/storage/backpack/marine/smartpack))
- var/obj/item/storage/backpack/marine/smartpack/s_pack = grabber.back
- if(grabber.action_busy)
- return
-
- if(!do_after(grabber, 20, INTERRUPT_ALL, BUSY_ICON_GENERIC))
+ if((grabber.species.flags & IS_SYNTHETIC))
+ if(istype(grabber.gloves, /obj/item/clothing/gloves/synth))
+ var/obj/item/clothing/gloves/synth/bracer = grabber.gloves
+ bracer.handle_apc_charge(grabber, src)
return
- playsound(src.loc, 'sound/effects/sparks2.ogg', 25, 1)
+ if(istype(grabber.back, /obj/item/storage/backpack/marine/smartpack))
+ var/obj/item/storage/backpack/marine/smartpack/s_pack = grabber.back
+ if(grabber.action_busy)
+ return
- if(stat & BROKEN)
- var/datum/effect_system/spark_spread/spark = new()
- spark.set_up(3, 1, src)
- spark.start()
- to_chat(grabber, SPAN_DANGER("The APC's power currents surge eratically, damaging your chassis!"))
- grabber.apply_damage(10,0, BURN)
- else if(cell && cell.charge > 0)
- if(!istype(s_pack))
+ if(!do_after(grabber, 20, INTERRUPT_ALL, BUSY_ICON_GENERIC))
+ return
+ if(!grabber.Adjacent(src) || (grabber.back != s_pack))
return
- if(s_pack.battery_charge < SMARTPACK_MAX_POWER_STORED)
- var/charge_to_use = min(cell.charge, SMARTPACK_MAX_POWER_STORED - s_pack.battery_charge)
- if(!(cell.use(charge_to_use)))
+ playsound(src.loc, 'sound/effects/sparks2.ogg', 25, 1)
+
+ if(stat & BROKEN)
+ var/datum/effect_system/spark_spread/spark = new()
+ spark.set_up(3, 1, src)
+ spark.start()
+ to_chat(grabber, SPAN_DANGER("The APC's power currents surge eratically, damaging your chassis!"))
+ grabber.apply_damage(10,0, BURN)
+ else if(cell && cell.charge > 0)
+ if(!istype(s_pack))
return
- s_pack.battery_charge += charge_to_use
- to_chat(user, SPAN_NOTICE("You slot your fingers into the APC interface and siphon off some of the stored charge. [s_pack.name] now has [s_pack.battery_charge]/[SMARTPACK_MAX_POWER_STORED]"))
- charging = APC_CHARGING
+
+ if(s_pack.battery_charge < SMARTPACK_MAX_POWER_STORED)
+ var/charge_to_use = min(cell.charge, SMARTPACK_MAX_POWER_STORED - s_pack.battery_charge)
+ if(!(cell.use(charge_to_use)))
+ return
+ s_pack.battery_charge += charge_to_use
+ to_chat(user, SPAN_NOTICE("You slot your fingers into the APC interface and siphon off some of the stored charge. [s_pack.name] now has [s_pack.battery_charge]/[SMARTPACK_MAX_POWER_STORED]"))
+ charging = APC_CHARGING
+ else
+ to_chat(user, SPAN_WARNING("[s_pack.name] is already fully charged."))
else
- to_chat(user, SPAN_WARNING("[s_pack.name] is already fully charged."))
- else
- to_chat(user, SPAN_WARNING("There is no charge to draw from that APC."))
- return
+ to_chat(user, SPAN_WARNING("There is no charge to draw from that APC."))
+ return
// Yautja Bracer Recharge
var/obj/item/clothing/gloves/yautja/bracer = grabber.gloves
diff --git a/code/modules/projectiles/guns/smartgun.dm b/code/modules/projectiles/guns/smartgun.dm
index a47480a6b257..6fac7b36afe4 100644
--- a/code/modules/projectiles/guns/smartgun.dm
+++ b/code/modules/projectiles/guns/smartgun.dm
@@ -46,7 +46,7 @@
var/range = 7
var/angle = 2
var/list/angle_list = list(180,135,90,60,30)
- var/obj/item/device/motiondetector/sg/MD
+ var/obj/item/device/motiondetector/integrated/MD
var/long_range_cooldown = 2
var/recycletime = 120
var/cover_open = FALSE
diff --git a/colonialmarines.dme b/colonialmarines.dme
index 5961c30df212..f8a4e903a9c3 100644
--- a/colonialmarines.dme
+++ b/colonialmarines.dme
@@ -1266,6 +1266,19 @@
#include "code\game\objects\items\tools\misc_tools.dm"
#include "code\game\objects\items\tools\shovel_tools.dm"
#include "code\game\objects\items\tools\surgery_tools.dm"
+#include "code\game\objects\items\tools\synth_bracer\_defines.dm"
+#include "code\game\objects\items\tools\synth_bracer\bracer_subtypes.dm"
+#include "code\game\objects\items\tools\synth_bracer\synth_bracer.dm"
+#include "code\game\objects\items\tools\synth_bracer\abilities\chips.dm"
+#include "code\game\objects\items\tools\synth_bracer\abilities\framework.dm"
+#include "code\game\objects\items\tools\synth_bracer\abilities\integrated\crew_monitor.dm"
+#include "code\game\objects\items\tools\synth_bracer\abilities\integrated\ocular_designator.dm"
+#include "code\game\objects\items\tools\synth_bracer\abilities\integrated\tactical_map.dm"
+#include "code\game\objects\items\tools\synth_bracer\abilities\primary\anchor_form.dm"
+#include "code\game\objects\items\tools\synth_bracer\abilities\primary\protect_form.dm"
+#include "code\game\objects\items\tools\synth_bracer\abilities\primary\repair_form.dm"
+#include "code\game\objects\items\tools\synth_bracer\abilities\utility\motion_detector.dm"
+#include "code\game\objects\items\tools\synth_bracer\abilities\utility\rescue_hook.dm"
#include "code\game\objects\items\toys\cards.dm"
#include "code\game\objects\items\toys\crayons.dm"
#include "code\game\objects\items\toys\toy_weapons.dm"
diff --git a/icons/mob/humans/onmob/synth/bracer.dmi b/icons/mob/humans/onmob/synth/bracer.dmi
new file mode 100644
index 000000000000..7016738afd67
Binary files /dev/null and b/icons/mob/humans/onmob/synth/bracer.dmi differ
diff --git a/icons/obj/items/synth/bracer.dmi b/icons/obj/items/synth/bracer.dmi
new file mode 100644
index 000000000000..dd6c30a874b3
Binary files /dev/null and b/icons/obj/items/synth/bracer.dmi differ