From 0a90983d75e1b5abb9daecc946be7e0cc10fba00 Mon Sep 17 00:00:00 2001 From: NervanCatos <32654903+MobiusWon@users.noreply.github.com> Date: Thu, 15 Feb 2024 20:01:18 -0600 Subject: [PATCH] XM4 Armor Integral Motion Detector (#5586) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # About the pull request Adds a motion detector action to the XM4 Intelligence Officer (IO) Armor. # Explain why it's good for the game 1. Currently there is no difference between the standard M4 "RTO" armor and the XM4 IO armor. The integral motion detector makes the X for "Experimental" meaningful. 2. The XM4 currently goes _mostly_ unused by IOs, this would change that. 3. The Motion Detector is already an essential item for IOs, this change distinguishes it from the other armor choices in game and adds a uniqueness to their piece of kit. 4. I envision the XM4 as the "safety" choice for IOs: it has extra storage, slower, and (with this feature) includes a Motion Detector to improve situational awareness. The other common choices for IOs are the Service Jacket I.E. the "speed" choice, and the M3-L armor a "middle ground" option. 5. This should not have any meaningful impact on balance vs. skirmishers as the Motion Detector is already an essential item for IOs. 6. Keep in mind the XM4 is only attainable by IOs and ~cannot be worn or purchased by anyone else.~ NOTE: This is my first "major" feature. I am open to suggestions, including "balance" related stuff. # Testing Photographs and Procedure https://github.com/cmss13-devs/cmss13/assets/32654903/445352b4-bfec-460f-95d8-2eadea27b953 Edit: Tested to confirm that the MD turns off upon user death. ✔️ # Changelog :cl: NervanCatos add: Adds integral Motion Detector to XM4 IO Armor balance: Uniform utility accessories (I.E. Webbing) no longer can be equipped while the XM4 is worn. Armor slots increased to 5 to compensate. /:cl: --------- Co-authored-by: Drathek <76988376+Drulikar@users.noreply.github.com> --- .../objects/items/devices/motion_detector.dm | 8 ++ code/modules/clothing/suits/marine_armor.dm | 116 +++++++++++++++++- code/modules/gear_presets/uscm.dm | 2 - .../mob/living/carbon/human/human_helpers.dm | 7 ++ 4 files changed, 130 insertions(+), 3 deletions(-) diff --git a/code/game/objects/items/devices/motion_detector.dm b/code/game/objects/items/devices/motion_detector.dm index c26db692f082..7db2825deedf 100644 --- a/code/game/objects/items/devices/motion_detector.dm +++ b/code/game/objects/items/devices/motion_detector.dm @@ -191,6 +191,14 @@ if(ishuman(A.loc)) return A.loc +/obj/item/device/motiondetector/xm4 + +///Forces the blue blip to appear around the detected mob +/obj/item/device/motiondetector/xm4/get_user() + var/atom/holder = loc + if(ishuman(holder.loc)) + return holder.loc + /obj/item/device/motiondetector/proc/apply_debuff(mob/M) return diff --git a/code/modules/clothing/suits/marine_armor.dm b/code/modules/clothing/suits/marine_armor.dm index 1be37df150a8..bc29b0a33570 100644 --- a/code/modules/clothing/suits/marine_armor.dm +++ b/code/modules/clothing/suits/marine_armor.dm @@ -281,8 +281,122 @@ /obj/item/clothing/suit/storage/marine/medium/rto/intel name = "\improper XM4 pattern intelligence officer armor" - uniform_restricted = list(/obj/item/clothing/under/marine/officer, /obj/item/clothing/under/rank/qm_suit, /obj/item/clothing/under/marine/officer/intel) + uniform_restricted = list(/obj/item/clothing/under/marine/officer/intel) specialty = "XM4 pattern intel" + desc = "Tougher than steel, quieter than whispers, the XM4 Intel Armor provides capable protection combined with an experimental integrated motion tracker. It took an R&D team a weekend to develop and costs more than the Chinook Station... probably. When worn, uniform accessories such as webbing cannot be attached due to the motion sensors occupying the clips." + desc_lore = "ARMAT Perfection. The XM4 Soldier Awareness System mixes M4-style hard armor and a distributed series of motion sensors clipped onto the breastplate. When connected to any HUD optic, it replicates the effects of an M314 Motion Detector unit, increasing user situational awareness. It is currently undergoing field trials by intelligence operatives." + storage_slots = 5 + /// XM4 Integral Motion Detector Ability + actions_types = list(/datum/action/item_action/toggle, /datum/action/item_action/intel/toggle_motion_detector) + var/motion_detector = FALSE + var/obj/item/device/motiondetector/xm4/proximity + var/long_range_cooldown = 2 + var/recycletime = 120 + +/obj/item/clothing/suit/storage/marine/medium/rto/intel/Initialize(mapload, ...) + . = ..() + proximity = new(src) + update_icon() + +/datum/action/item_action/intel/action_activate() + if(!ishuman(owner)) + return + +/datum/action/item_action/intel/update_button_icon() + return + +/datum/action/item_action/intel/toggle_motion_detector/New(Target, obj/item/holder) + . = ..() + name = "Toggle Motion Detector" + action_icon_state = "motion_detector" + button.name = name + button.overlays.Cut() + button.overlays += image('icons/mob/hud/actions.dmi', button, action_icon_state) + +/datum/action/item_action/intel/toggle_motion_detector/action_activate() + . = ..() + var/obj/item/clothing/suit/storage/marine/medium/rto/intel/recon = holder_item + recon.toggle_motion_detector(owner) + +/datum/action/item_action/intel/toggle_motion_detector/proc/update_icon() + if(!holder_item) + return + var/obj/item/clothing/suit/storage/marine/medium/rto/intel/recon = holder_item + if(recon.motion_detector) + button.icon_state = "template_on" + else + button.icon_state = "template" + +/obj/item/clothing/suit/storage/marine/medium/rto/intel/process() + if(!motion_detector) + STOP_PROCESSING(SSobj, src) + if(motion_detector) + recycletime-- + if(!recycletime) + recycletime = initial(recycletime) + proximity.refresh_blip_pool() + long_range_cooldown-- + if(long_range_cooldown) + return + long_range_cooldown = initial(long_range_cooldown) + proximity.scan() + +/obj/item/clothing/suit/storage/marine/medium/rto/intel/proc/toggle_motion_detector(mob/user) + to_chat(user,SPAN_NOTICE("You [motion_detector? "disable" : "enable"] \the [src]'s motion detector.")) + if(!motion_detector) + playsound(loc,'sound/items/detector_turn_on.ogg', 25, 1) + else + playsound(loc,'sound/items/detector_turn_off.ogg', 25, 1) + motion_detector = !motion_detector + var/datum/action/item_action/intel/toggle_motion_detector/TMD = locate(/datum/action/item_action/intel/toggle_motion_detector) in actions + TMD.update_icon() + motion_detector() + +/obj/item/clothing/suit/storage/marine/medium/rto/intel/proc/motion_detector() + if(motion_detector) + START_PROCESSING(SSobj, src) + else + STOP_PROCESSING(SSobj, src) + +/obj/item/clothing/suit/storage/marine/medium/rto/intel/mob_can_equip(mob/living/carbon/human/user, slot, disable_warning) //Thanks to Drathek for the help on this part! + if(!..()) + return FALSE + + // Only equip if uniform doesn't already have a utility accessory slot equipped + var/obj/item/clothing/under/uniform = user.w_uniform + var/accessory = locate(/obj/item/clothing/accessory/storage) in uniform.accessories + if(accessory) + to_chat(user, SPAN_WARNING("[src] can't be worn with [accessory].")) + return FALSE + // Only equip if user has expert intel skill level + if(!skillcheck(user, SKILL_INTEL, SKILL_INTEL_EXPERT)) + to_chat(user, SPAN_WARNING("You don't seem to know how to use [src]...")) + return FALSE + return TRUE + +/obj/item/clothing/suit/storage/marine/medium/rto/intel/equipped(mob/user, slot, silent) //When XM4 is equipped this removes ACCESSORY_SLOT_UTILITY as a valid accessory for the uniform + . = ..() + if(slot == WEAR_JACKET) + var/mob/living/carbon/human/human = user + var/obj/item/clothing/under/uniform = human.w_uniform + if(uniform?.valid_accessory_slots) + uniform?.valid_accessory_slots -= ACCESSORY_SLOT_UTILITY + +/obj/item/clothing/suit/storage/marine/medium/rto/intel/unequipped(mob/user, slot) //When unequipped this adds the ACCESSORY_SLOT_UTILITY back as a valid accessory + . = ..() + if(slot == WEAR_JACKET) + var/mob/living/carbon/human/human = user + var/obj/item/clothing/under/uniform = human.w_uniform + if(uniform) + // Figure out if the uniform originally allowed ACCESSORY_SLOT_UTILITY + var/obj/item/clothing/under/temp_uniform = new uniform.type + if(temp_uniform.valid_accessory_slots) + for(var/allowed in temp_uniform.valid_accessory_slots) + if(allowed == ACCESSORY_SLOT_UTILITY) + // It was allowed previously, now add it back + uniform.valid_accessory_slots += ACCESSORY_SLOT_UTILITY + break + qdel(temp_uniform) /obj/item/clothing/suit/storage/marine/MP name = "\improper M2 pattern MP armor" diff --git a/code/modules/gear_presets/uscm.dm b/code/modules/gear_presets/uscm.dm index 8f5243edf84d..5402a5ed7305 100644 --- a/code/modules/gear_presets/uscm.dm +++ b/code/modules/gear_presets/uscm.dm @@ -251,8 +251,6 @@ /datum/equipment_preset/uscm/intel/full/load_gear(mob/living/carbon/human/new_human) var/obj/item/clothing/under/marine/officer/intel/U = new(new_human) - var/obj/item/clothing/accessory/storage/webbing/W = new() - U.attach_accessory(new_human, W) new_human.equip_to_slot_or_del(U, WEAR_BODY) new_human.equip_to_slot_or_del(new /obj/item/device/radio/headset/almayer/intel(new_human), WEAR_L_EAR) new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/knife(new_human), WEAR_FEET) diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index 08ddd11da5b3..c38ddbcd552c 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -247,6 +247,13 @@ var/datum/action/item_action/smartgun/toggle_motion_detector/TMD = locate(/datum/action/item_action/smartgun/toggle_motion_detector) in sg.actions TMD.update_icon() sg.motion_detector() + if(istype(i, /obj/item/clothing/suit/storage/marine/medium/rto/intel)) + var/obj/item/clothing/suit/storage/marine/medium/rto/intel/xm4 = i + if(xm4.motion_detector) + xm4.motion_detector = FALSE + var/datum/action/item_action/intel/toggle_motion_detector/TMD = locate(/datum/action/item_action/intel/toggle_motion_detector) in xm4.actions + TMD.update_icon() + xm4.motion_detector() /mob/living/carbon/human/proc/disable_headsets() //Disable all radios to reduce radio spam for dead people