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